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