防止基类构造函数在无效的派生类初始化程序上调用

问题描述 投票:0回答:3

请考虑以下示例,其中Derived类的构造在其构造函数的初始化程序列表上使用一个指针。当然,我想检查该指针是否有效,否则抛出异常。

我的尝试防止了程序崩溃,但是在抛出异常之前,仍然构造了Base部分。

有没有一种方法可以防止在这种情况下调用Base类构造函数?

#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;
}
c++ constructor derived-class
3个回答
4
投票

您可以在调用Base构造函数之前调用函数/ lambda:

Derived::Derived(int *val1, int val2) :
    Base([&](){
        if (!val1) {
            throw std::invalid_argument("bad pointer");
        }
        return *val1;
    }()),
    val_d(val2) 
{
}

0
投票

也许我会误解您的问题,但请考虑以下简化示例:

#include <iostream>

struct Base {
    ~Base() { std::cout <<"destructor";}
};
struct Foo : Base {
    Foo() : Base() {
        throw 1;
    }
};
int main()
{
    try {
        Foo f;
    } catch(...){}
}

输出为:

destructor

我的尝试避免了程序崩溃,但是在抛出异常之前,基本部分仍已构建。

这没问题。与往常一样,堆栈会展开,并且BaseFoo部分会被正确破坏。我认为您的代码没有任何错误(尽管设计有争议,但严重受损)。如果构造失败,并且您在构造函数的主体中抛出异常,则尽力清除已经构造的内容。


0
投票

我不知道为什么要这么做,但是无论如何,您是否尝试过使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;
};
© www.soinside.com 2019 - 2024. All rights reserved.