首页 文章

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

提问于
浏览
2

我有一个带有成员变量的基类(最好是 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 的另一个定义没有't hide the default constructor. I'仍然停留在未初始化的 Base::_size 上 .

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

任何指针都表示赞赏 .

2 回答

  • 0

    关于调用基类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;
        /* ... */
    };
    
  • 2

    使用构造函数

    class Base1 {protected:Base1(int forward) private: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是未定义的引用 .

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

相关问题