强制子类实现并调用(一次)方法
Force sub-classes to implement and call (once) a method
我正在寻找一种方法来创建必须由每个子类实现的方法。我还希望子类在构造上调用此方法。
在类构造之后应该无法再次调用此方法。
#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;
}
这是一个示例,但它无效,因为它在构造函数中调用纯虚拟方法。当然,我可以在每个子类构造函数中添加init()
,但是在新子类上可能会忘记它。
这样做的C++方法是什么?
C++方法是不这样做。初始化函数不好。只需使用构造函数。
AFAIK,在构造函数中调用虚函数是非常危险的。下面是一个简单的示例。我稍微修改了您的代码,以使该方法也Base
类中实现init
:
#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 base
Hello, I am A.
Hello, I am B.
我们可以得出什么结论:
- 一旦对象被构造,一切都很好,当我们调用
init
方法时,我们通常会从派生类中获得正确的实现 但在构造函数中,顺序是:
- 调用构造
Base
函数 - 从 Base 对象调用 init 方法(因为派生对象尚未构造)
- 调用构造
DerivedX
因此,该方法始终是来自
Base
的方法,这绝对不是您所期望的。- 调用构造
正如另一张海报所说,您可能应该远离这种情况,但最简单的示例是在 Base 上创建一个名为 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
}
}
或:
template<Initializer TInitializer>
class Base<TInitializer> {
public:
Base() {
TInitializer initializer;
// Get members from initializer
}
}
抱歉,我没有写太长C++,所以我可以防止一些语法错误。
C++11 的call_once可以让你大部分时间,但它有成本。
- 该类将不可移动或复制。
- 您必须在每个需要初始化的函数中添加一行额外的行。
它不会阻止多次调用该方法,但这很容易添加。
#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;
};
请注意,派生类除了提供v_init之外,没有任何特殊之处。
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;
}
输出:请注意,将调用v_init哪个示例函数首先调用,而不是在 ctors 中调用。
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
相关文章:
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 访问随机图像像素的快速方法,最多一次
- 只设置一次方法中变量的值
- cppUnit:针对多个测试方法执行一次的设置函数
- 是否有一种方法可以在运行时停止循环重复一次不止一次
- 快速简单的方法,以C++为单位一次读取一个字节的 stdin
- 最简单的方法使多个指针一次指向同一位置,一次只处理2个位置
- C++菱形问题 - 如何仅调用一次基方法
- 搜索字符串是否至少包含一次从 0 到 9 的所有数字的最有效方法
- 当Bool值在UPDATE()方法中更改时,只有一次呼叫函数
- 有没有一种方法可以使全局函数/静态成员函数一次可呼出
- 有没有一种优雅的方法,根据用户输入只决定一次
- 如何确保方法在该对象的生存期内仅执行一次?
- 在方法中构造一个std:映射一次
- 只为NOT STATIC类的EACH对象调用一次方法
- 在继承层次结构中将方法定义为虚拟方法一次,以使多态性发挥作用
- C++将节点添加到链表的开头一次后失败.其他方法也有问题
- QTimer 每秒执行一次方法
- 如何只执行一次方法代码,尽管每帧调用一次
- 从类中只调用一次方法