我找到了一些正在处理的代码,并且想知道最佳设计实现是什么。
如果一个基类将一个方法定义为虚拟,但也实现了一个空体,因此不需要派生类实现一个体,那么它是不是应该变成纯粹的呢?
virtual void AMethod1() {} // 1
virtual void AMethod2() {assert(false);} // 2
virtual void AMethod3() = 0; // 3
你是什么,值得信赖的神奇SO人,你会怎么想?
Edit1:发帖(并阅读答案)后,我意识到断言很糟糕!
virtual void AMethod3() = {throw (ENotImplemented)}; // 4
答案 0 :(得分:9)
这取决于你的编码风格是多么“纯粹”。有些人认为你应该总是只用纯虚函数定义一个接口,并从中派生出所有具体的类。
其他人更务实,相信如果有一个好的默认实现,你可以将它添加到基类(选项1)。
第二个选项似乎是最不实用的,因为它将检测延迟到运行时。大多数程序员宁愿选择选项3中的编译错误。
像往常一样,C ++支持几种范例,您可以选择自己喜欢的范例。
答案 1 :(得分:6)
如果派生类必须实现此方法,则应使用选项3。如果在派生类中实现是可选的,请使用选项1。完全避免使用选项2.
答案 2 :(得分:3)
如果一个基类将一个方法定义为虚拟,但也实现了一个空体,因此不需要派生类实现一个体,那么它是不是应该变为纯粹的呢?
这取决于您是否希望强制派生类来覆盖该方法。如果你这样做,那么使用纯virtual
;它完全符合该要求的语言支持。如果稍后有或可能是amethod
的默认实现,则使用纯virtual
方法实现:
class Foo {
virtual void amethod() = 0;
};
void Foo::amethod() {
// whatever
}
该函数现在仍然是纯virtual
,因此Foo
类无法实例化,但任何派生类都将继承实现,其方法可以将其称为Foo::amethod
。
答案 3 :(得分:2)
制作方法纯虚拟比使用断言进行默认实施更直观。如果什么都不做是大多数情况下的默认实现,那么当前代码会更好。当然,如果你想使用多态,它应该保持虚拟。
答案 4 :(得分:2)
我已经看过很多这样的例子,你需要实例化这个类,所以
你将virtual
与空体一起使用:
virtual void AMethod1() {} // 1
如果要强制派生类重写,请使用此选项 此功能,您不需要默认值:
virtual void AMethod3() = 0; // 3
所以这真的取决于你想做什么。
答案 5 :(得分:2)
virtual void AMethod1() = 0;
:如果您的基类没有实现提供 AND ,当此行为应该<时,纯虚拟是最好的/ strong>实施。 (这是你问题中的选项3)
virtual void AMethod1() {}
:如果您的基类没有实现提供 AND 此行为 MAY 实施。 (这是你问题中的选项1)
virtual void AMethod1() { assert(false); }
:在我看来,必须避免使用assert(false)
的虚拟广告。我认为没有任何有效用途。上述两个选项涵盖了所有用例的基本原理:行为可能或应,因此无法定义可调用方法总是失败。编译器可以通过阻止此调用来为您处理,因此该选项通过将此检查推迟到运行时来引入风险。 (这是你问题中的选项2)
答案 6 :(得分:1)
如果不这样做,我们应该使用纯虚函数 想要实例化一个类,但让它充当基类 对于从中衍生出来的所有类。
重要的是 关于纯虚函数的注意就是这些 必须在所有派生类中重写函数 否则编译会标记出错误。
很简单,
class alpha {
public:virtual void show()=0; //pure virtual function
};
class beta : public alpha {
public:void show() //overriding
{
cout<<"OOP in C++";
}
};
void main() {
alpha *p;
beta b;
p=&b;
p->show();
}
答案 7 :(得分:1)
因为你需要virtual
机制;以下是我的简短回答:
(1)
virtual void AMethod1() {}
要求:
- Allow creating objects of base class
- Base `virtual` method is use.
(2) virtual void AMethod2() {assert(false);}
要求:
- Allow creating objects of base class
- Base method is not used
- Force derived classes to implement the method (hard way, because it happens at runtime).
(3) virtual void AMethod3() = 0;
要求:
- Don't allow base class object creation
- Force derived classes to implement the method at compile time
答案 8 :(得分:1)
如果基类将方法定义为虚拟,但实现为空 身体也是如此,因此不需要派生类来实现 一个身体,不应该变得纯净吗?
这取决于您的设计。如果您的方法是纯虚拟的,那么您将向派生类开发人员发送一条消息,告知“您必须在此处放置一些实际代码,以使您的课程正常工作”。另一方面,如果您的方法是虚拟的空体,则消息是“您可能在此处放置一些代码,但这取决于您的实际需求”。
virtual void AMethod1() {} // 1
virtual void AMethod2() {assert(false);} // 2
virtual void AMethod3() = 0; // 3
我肯定更喜欢选项3而不是2,如果派生类没有实现虚方法,它将产生编译错误而不是运行时错误。
答案 9 :(得分:0)
没有简单的规则:
如果某些派生类有意义,请使用1(空实现) 如果调用该函数则不执行任何操作。
如果派生类没有实现,则使用3 功能
在极少数情况下使用2,其中函数的前提条件是
另一个虚函数hare返回true,该函数有一个
默认实现返回false(或沿着这些行的东西)。
基本上,如果界面的一部分是可选的。 (但通常,它是
在这种情况下更好地导出界面;实现的类
扩展接口派生自它,客户想要使用它
dynamic_cast
扩展接口。)
根据经验(但你的编程风格可能不同),1似乎至少有90%的时间适用,而且我认为在二十多年的C ++中,我曾经使用过3次,或者两次。