C ++:如何强制派生类来设置基本成员变量?

时间:2013-10-08 23:12:30

标签: c++ inheritance

我有一个带有成员变量的基类(最好是private),我需要强制派生类用基于其实现的值初始化它;很像一个纯虚函数。

为了澄清,我想在Base中声明一个成员,派生类初始化它,如果不是,则会出现编译器错误。在以下代码中,我将Base的默认构造函数声明为protected。然后将Derived的默认构造函数声明为private

class Base {
private:
    int _size;

protected:
    Base(){}
    /* pure virtual methods */

public:
    Base(int size) : _size(size){} // must enforce derived to call this.
    virtual ~Base(){}

    /* more pure virtual methods */
};

class Derived : public Base {
private:
    Derived() {}
public:
    Derived(int size) : Base(size) {
        //Base::Base(size);
    }
};

int main()
{
    Derived* d1 = new Derived();    // throws an error as needed: 
                                    // "Cannot access private member declared in class 'Derived'"

    Derived* d2 = new Derived;      // throws an error as needed: 
                                    // "Cannot access private member declared in class 'Derived'"

    Derived* d3 = new Derived(5);   // works as needed

    return 0;
}

上面代码的问题是,如果Derived的另一个定义没有隐藏默认构造函数。我仍然坚持使用未初始化的Base::_size

我不知道除了继承之外是否还有其他方法可以解决这个问题,因为我仍然需要派生类来为Base中声明的几个方法实现自己的行为。

任何指针都表示赞赏。

2 个答案:

答案 0 :(得分:2)

关于调用基类ctor和默认ctors的困惑之后,或许解决方案是在Base中没有默认的ctor?

class Base {
private:
    int _size;

public:
    // no default ctor
    Base(int size) : _size(size) {} // must enforce derived to call this.
    virtual ~Base(){}

    /* more pure virtual methods */
};

class Derived : public Base {
public:
    // no default ctor
    Derived(int size) : Base(size){
    }
    // examplary default ctor:
    //Derived() : Base(42) {}
};

int main()
{
    Derived d1;                   // error: no default ctor
    Derived* d2 = new Derived;    // same, but why use the free store?

    Derived d3(5);                // works as needed
    Derived* d4 = new Derived(5); // same, but why use the free store?

    return 0;
}

要明确没有默认的ctor,可以使用

class Base {
    /* ... */
    Base() = delete;
    /* ... */
};

答案 1 :(得分:0)

使用构造函数

类Base1 {     保护:         Base1(int forward){             thingYouWantToHide = forward;         }     私人的:         int thingYouWantToHide;     };

class Derived1: public Base1 {
public:
    Derived1(): Base1(5) {}
};

class Base2 {
private:
    int value;
protected:
    Base2() {
        value = calledToGet();
    }
    virtual int calledToGet() = 0;

    virtual ~Base2() {} //shut compiler warnings up
};

class Derived2: public Base2 {
    virtual int calledToGet() {
        return 5;
    }
};

int main(int,char**) {
    Derived1 a;
    Derived2 b;
    return 0;
}

你可能认为Derived2会起作用,但是记住Derived2在构造Base2之前不构造,所以当构造Base2时,virtual是一个未定义的引用。

你应该使用第一种情况,类型特征,如果它是常量(静态常量)或类型的基础。