防止在无效的 Derived class 初始值设定项上调用 Base class 构造函数
Prevent Base class constructor being called on invalid Derived class initializer
考虑以下示例,其中 Derived
class 的构造在其构造函数的初始化列表中采用指针。当然我想检查这个指针是否有效,否则抛出异常。
我的尝试阻止了程序崩溃,但 Base
部分在我抛出异常之前仍在构造中。
有什么方法可以防止在这种情况下调用 Base
class 构造函数?
#include <stdlib.h>
#include <iostream>
class Base
{
public:
Base(int val) : val_b(val)
{
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
class Derived : public Base
{
public:
Derived(int *, int);
~Derived() { }
int val_d;
void print(void)
{
std::cout << "Base:\t" << val_b << std::endl;
std::cout << "Derived:" << val_d << std::endl;
}
};
Derived::Derived(int *val1, int val2) : Base(val1 ? *val1 : -1), val_d(val2)
{
if (!val1)
{
throw std::invalid_argument("bad pointer");
}
}
int main()
{
int *a = NULL;
int b = 43;
try
{
Derived *d = new Derived(a, b);
d->print();
}
catch (std::exception &e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
return 0;
}
也许我误解了你的问题,但考虑这个简化的例子:
#include <iostream>
struct Base {
~Base() { std::cout <<"destructor";}
};
struct Foo : Base {
Foo() : Base() {
throw 1;
}
};
int main()
{
try {
Foo f;
} catch(...){}
}
输出为:
destructor
My attempt prevents the program to crash but Base part is still constructed before I can throw the exception.
这不是问题。与往常一样,堆栈被展开并且 Foo
的 Base
部分被正确销毁。我看不出你的代码有什么问题(在严重破坏的意义上,尽管设计值得商榷)。如果构造失败并且您在构造函数的主体中抛出异常,那么清理已经构造的内容是您能做的最好的事情。
我不明白你为什么想要它,但无论如何你试过在 Base ctor 而不是 Derived ctor 中失败吗?
class Base
{
public:
Base(int *val)
{
if (!val)
{
throw std::invalid_argument("bad pointer");
}
val_b = val;
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
您可以在调用 Base 构造函数之前调用 function/lambda:
Derived::Derived(int *val1, int val2) :
Base([&](){
if (!val1) {
throw std::invalid_argument("bad pointer");
}
return *val1;
}()),
val_d(val2)
{
}
考虑以下示例,其中 Derived
class 的构造在其构造函数的初始化列表中采用指针。当然我想检查这个指针是否有效,否则抛出异常。
我的尝试阻止了程序崩溃,但 Base
部分在我抛出异常之前仍在构造中。
有什么方法可以防止在这种情况下调用 Base
class 构造函数?
#include <stdlib.h>
#include <iostream>
class Base
{
public:
Base(int val) : val_b(val)
{
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
class Derived : public Base
{
public:
Derived(int *, int);
~Derived() { }
int val_d;
void print(void)
{
std::cout << "Base:\t" << val_b << std::endl;
std::cout << "Derived:" << val_d << std::endl;
}
};
Derived::Derived(int *val1, int val2) : Base(val1 ? *val1 : -1), val_d(val2)
{
if (!val1)
{
throw std::invalid_argument("bad pointer");
}
}
int main()
{
int *a = NULL;
int b = 43;
try
{
Derived *d = new Derived(a, b);
d->print();
}
catch (std::exception &e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
return 0;
}
也许我误解了你的问题,但考虑这个简化的例子:
#include <iostream>
struct Base {
~Base() { std::cout <<"destructor";}
};
struct Foo : Base {
Foo() : Base() {
throw 1;
}
};
int main()
{
try {
Foo f;
} catch(...){}
}
输出为:
destructor
My attempt prevents the program to crash but Base part is still constructed before I can throw the exception.
这不是问题。与往常一样,堆栈被展开并且 Foo
的 Base
部分被正确销毁。我看不出你的代码有什么问题(在严重破坏的意义上,尽管设计值得商榷)。如果构造失败并且您在构造函数的主体中抛出异常,那么清理已经构造的内容是您能做的最好的事情。
我不明白你为什么想要它,但无论如何你试过在 Base ctor 而不是 Derived ctor 中失败吗?
class Base
{
public:
Base(int *val)
{
if (!val)
{
throw std::invalid_argument("bad pointer");
}
val_b = val;
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
您可以在调用 Base 构造函数之前调用 function/lambda:
Derived::Derived(int *val1, int val2) :
Base([&](){
if (!val1) {
throw std::invalid_argument("bad pointer");
}
return *val1;
}()),
val_d(val2)
{
}