C++ 强制子类实现并调用(一次)方法

C++ 强制子类实现并调用(一次)方法,c++,C++,我正在寻找一种方法来创建一个必须由每个子类实现的方法。我还希望子类在构造时调用此方法 在类构造之后,应该不可能再次调用此方法 #include <iostream> class Base { public: Base() {init();} private: virtual void init() = 0; }; class DerivedA : public Base { public: DerivedA() {} private: virtual

我正在寻找一种方法来创建一个必须由每个子类实现的方法。我还希望子类在构造时调用此方法

在类构造之后,应该不可能再次调用此方法

#include <iostream>
class Base {
public:
    Base() {init();}
private:
    virtual void init() = 0;
};

class DerivedA : public Base {
public:
    DerivedA() {}
private:
    virtual void init() { std::cout << "Hello, I am A.";}
};

class DerivedB : public Base{
public:
    DerivedB() {}
private:
    virtual void init() {std::cout << "Hello, I am B.";}
};

int main(){
    DerivedA a;
    DerivedB b;
    return 0;
}
#包括
阶级基础{
公众:
Base(){init();}
私人:
虚拟void init()=0;
};
DerivedA类:公共基础{
公众:
DerivedA(){}
私人:

虚空隙init():STD::CUT> P> C++是不做这件事的。init函数是坏的。只需使用构造函数。

,正如另一张海报所说的,你应该远离这个,但是最简单的例子是在基数(init)上创建一个公共的非虚接口方法。该方法可以调用派生类上的纯虚拟“DoInit”方法,并跟踪是否已使用内部标志调用该方法

我不推荐这个,但它会起作用的

class Base
{
public:
    void Init()
    {
        if(!initialized)
        {
            DoInit();
            initialized = true;
        }
    }
protected:
    virtual void DoInit() = 0; // derived classes need to implement this
private:
    bool initialized {false};
};

我遇到了类似的问题,无法找到简单的解决方案。我必须在单独的类中进行初始化。此类的对象可以传递给基/派生构造函数,或者此类可以是模板参数

class Initializer {
    . . .
}

class Base {
public:
    Base(Initializer* initializer) {
        // Get members from initializer
    }
}
或:

模板
阶级基础{
公众:
Base(){
替硝唑初始化剂;
//从初始值设定项获取成员
}
}

对不起,我在C++中写的时间太长了,所以我不能防止一些语法错误。

AFIK,调用构造函数中的虚函数是非常危险的。这里有一个简单的例子。我稍微修改了你的代码,使其具有<代码> init < /> >方法,也在 Base< /Cuff>类:

中实现。
#include <iostream>
#include <exception>

class Base {
protected:
    Base() {init() ; }

    virtual void init() {
        std::cout << "Init base" << std::endl;
    }
public:
    void callinit() {
        init();
    }
};

class DerivedA : public Base {
public:
    DerivedA() {}
protected:
    virtual void init() { std::cout << "Hello, I am A."<< std::endl;}
};

class DerivedB : public Base{
public:
    DerivedB() {}
protected:
    virtual void init() {std::cout << "Hello, I am B."<< std::endl;}
};

int main(){
    DerivedA a;
    DerivedB b;
    a.callinit();
    b.callinit();
    return 0;
}
我们可以得出什么结论:

  • 一旦构建了对象,一切都很好,当我们调用
    init
    方法时,我们通常从派生类得到正确的实现
  • 但在构造函数中,顺序是:

    • 调用
      Base
      构造函数
    • 从基对象调用init方法(因为中的派生对象尚未构造)
    • 调用
      DerivedX
      构造函数
    因此,该方法始终是来自
    Base
    的方法,这肯定不是您所期望的


C++11的调用曾经让你获得了大部分的成功,但它有成本

  • 该类将不可移动,也不可复制
  • 必须在每个需要初始化的函数中添加额外的行
  • 它不会阻止方法被多次调用,但这很容易添加

    #include <iostream>
    #include <mutex>
    
    struct Base {
        Base() {
            std::cout << "Base ctor" << std::endl;
        }
    
        void sampleFunction1() {
            // this line must be at the start of every function that needs the initialization
            std::call_once(initedFlag, &Base::v_init, this);
    
            std::cout << "Base::sampleFunction1" << std::endl;
        }
    
        void sampleFunction2() {
            // this line must be at the start of every function that needs the initialization
            std::call_once(initedFlag, &Base::v_init, this);
    
            std::cout << "Base::sampleFunction2" << std::endl;
        }
    
    private:
        virtual void v_init() = 0;
        std::once_flag initedFlag;
    };
    

    你为什么要这么做?
    Init base
    Init base
    Hello, I am A.
    Hello, I am B.
    
    #include <iostream>
    #include <mutex>
    
    struct Base {
        Base() {
            std::cout << "Base ctor" << std::endl;
        }
    
        void sampleFunction1() {
            // this line must be at the start of every function that needs the initialization
            std::call_once(initedFlag, &Base::v_init, this);
    
            std::cout << "Base::sampleFunction1" << std::endl;
        }
    
        void sampleFunction2() {
            // this line must be at the start of every function that needs the initialization
            std::call_once(initedFlag, &Base::v_init, this);
    
            std::cout << "Base::sampleFunction2" << std::endl;
        }
    
    private:
        virtual void v_init() = 0;
        std::once_flag initedFlag;
    };
    
    struct Derived : Base {
    
        Derived() {
            std::cout << "Derived ctor" << std::endl;
        }
    
    private:
        void v_init() override {
            std::cout << "Derived::v_init" << std::endl;
        }
    };
    
    int main(int argc, const char * argv[]) {
        Derived d1;
        Derived d2;
        std::cout << "Calling d1" << std::endl;
        d1.sampleFunction1();
        d1.sampleFunction2();
        std::cout << "Calling d2" << std::endl;
        d2.sampleFunction2();
        d2.sampleFunction1();
        return 0;
    }
    
    Base ctor
    Derived ctor
    Base ctor
    Derived ctor
    Calling d1
    Derived::v_init
    Base::sampleFunction1
    Base::sampleFunction2
    Calling d2
    Derived::v_init
    Base::sampleFunction2
    Base::sampleFunction1