虚方法什么时候应该是纯方法?

发布于 2024-11-26 19:59:49 字数 532 浏览 4 评论 0原文

我找到了一些我正在处理的代码,并且想知道最好的设计实现是什么。

如果基类将一个方法定义为虚拟方法,但也实现了一个空主体,因此不需要派生类实现主体,那么它不应该成为纯方法吗?

virtual void AMethod1() {}                 // 1
virtual void AMethod2() {assert(false);}   // 2
virtual void AMethod3() = 0;               // 3
  1. 当前代码。
  2. 想法1:提醒用户该派生对象尚未实现该方法体。
  3. 想法2:强制派生类实现主体,无论是否为空。

你们这些值得信赖的令人惊叹的SO人怎么想?


Edit1:发布(并阅读答案)后,我意识到断言很糟糕!

virtual void AMethod3() = {throw (ENotImplemented)};               // 4

I have found some code that I am working on, and was wondering what the best design implementation is.

If a base class defines a method as virtual, but implements an empty body as well, thus not requiring the derived classes to implement a body, should it not be made pure instead?

virtual void AMethod1() {}                 // 1
virtual void AMethod2() {assert(false);}   // 2
virtual void AMethod3() = 0;               // 3
  1. Current code.
  2. Idea1: Alerts user that this derived object has not implemented this method body.
  3. Idea2: Forces derived classes to implement a body, empty or not.

What do you, the trusted amazing SO people, think?


Edit1: After posting (and reading answers), I realize that assert is bad!

virtual void AMethod3() = {throw (ENotImplemented)};               // 4

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

人心善变 2024-12-03 19:59:49

这在一定程度上取决于您的编码风格的“纯粹”程度。有些人认为您应该始终仅定义一个仅包含纯虚函数的接口,并从中派生所有具体类。

其他人则更加务实,认为如果有一个好的默认实现,您可以将其添加到基类中(选项 1)。

第二个选项似乎最没用,因为它将检测延迟到运行时。大多数程序员宁愿选择选项 3 中的编译错误。

像往常一样,C++ 支持多种范例,您可以选择您喜欢的一种。

It depends a bit on how "pure" your coding style is. Some people believe that you should always define an interface with pure virtual functions only and derive all concrete classes from that.

Others are more pragmatic and belive that if there is a good default implementation, you can add that to the base class (option 1).

The second option seems to be the least useful, as it delays detection until runtime. Most programmers would rather prefer a compilation error from option 3.

As usual, C++ supports several paradigms and you can choose the one you prefer.

顾铮苏瑾 2024-12-03 19:59:49

如果派生类必须实现此方法,则应使用选项 3。如果在派生类中实现是可选的,则使用选项 1。完全避免选择 2。

You should use option 3 if the derived class must implement this method. Use option 1 if implementing in the derived class is optional. Avoid option 2 altogether.

我一直都在从未离去 2024-12-03 19:59:49

如果基类将方法定义为虚拟方法,但也实现了空主体,因此不需要派生类实现主体,那么它不应该成为纯方法吗?

这取决于您是否想要强制派生类重写该方法。如果你这样做,那么使用纯虚拟;它正是满足该要求的语言支持。如果存在或稍后可能存在amethod的默认实现,则使用带有实现的纯virtual方法:

class Foo {
    virtual void amethod() = 0;
};

void Foo::amethod() {
    // whatever
}

该函数现在仍然是纯virtual 因此,Foo 类无法实例化,但任何派生类都将继承该实现,并且其方法可以将其调用为 Foo::amethod

If a base class defines a method as virtual, but implements a empty body as well, thus not requiring the derived classes from implementing a body, should it not be made pure instead?

That depends on whether you want to force derived classes to override the method. If you do, then use a pure virtual; it's language support for exactly that requirement. If there is or may at a later point be a default implementation of amethod, then use a pure virtual method with an implementation:

class Foo {
    virtual void amethod() = 0;
};

void Foo::amethod() {
    // whatever
}

The function is now still pure virtual so the Foo class cannot be instantiated, but any derived class will inherit the implementation and its methods can call it as Foo::amethod.

梦毁影碎の 2024-12-03 19:59:49

使方法纯虚拟比使用断言进行默认实现更直观。在大多数情况下,如果不执行任何操作是默认实现,则当前代码会更好。当然,如果你想使用多态性,它应该保持虚拟。

Making method pure virtual is more intuitive than making default implementation with an assert. Current code is better if doing nothing is default implementation in most cases. Of course it should stay virtual if you want to use polymorphism.

情深已缘浅 2024-12-03 19:59:49
  • virtual void AMethod1() = 0;:当您的基类没有提供AND实现时,纯虚拟是最好的这种行为应该被实施。 (这是您问题中的选项 3)

  • virtual void AMethod1() {}:当您的基类没有提供实现时,具有空实现的虚拟是最好的并且当此行为可以实施时。 (这是您问题中的选项 1)

  • virtual void AMethod1() { assert(false); }:我认为必须避免带有 assert(false) 的虚拟。我没有看到它有任何有效的用途。其背后的基本原理是,所有用例都由上面的两个选项涵盖:实现行为可能应该,因此定义可调用方法是没有用的那总是失败。编译器可以通过阻止此调用来为您处理该问题,因此此选项通过将此检查推迟到运行时而引入风险。 (这是您问题中的选项2)

  • virtual void AMethod1() = 0;: A pure virtual is the best when your base class has no implementation to provide AND when this behaviour SHOULD be implemented. (This is option 3 in your question)

  • virtual void AMethod1() {}: A virtual with an empty implementation is the best when your base class has no implementation to provide AND when this behaviour MAY be implemented. (This is option 1 in your question)

  • virtual void AMethod1() { assert(false); }: A virtual with an assert(false) must be avoided in my opinion. I don't see any valid use for it. The rationale behind that being that all use cases are covered by the two options above: either the behaviour may or should is implemented, so there is no use to define a callable method that always fails. The compiler can handle that for you by preventing this call, so this option introduces a risk by postponing this checking to the run time. (This is option 2 in your question)

客…行舟 2024-12-03 19:59:49

我见过很多这样的例子,你需要实例化类,所以
您使用带有空主体的virtual

virtual void AMethod1() {}                 // 1

当您想要强制派生类重写时使用此选项
这个函数,你不需要默认值:

virtual void AMethod3() = 0;               // 3

所以这实际上取决于你想要做什么。

I have seen quite a few examples like this where you need to instantiate the class, so
you use virtual with a empty body:

virtual void AMethod1() {}                 // 1

Use this when you want to force the derived class to override
this function and you don't need a default:

virtual void AMethod3() = 0;               // 3

So it really depends on what you want to do.

生寂 2024-12-03 19:59:49

如果不这样做,我们应该使用纯虚函数
想要实例化一个类但使其充当基类
对于所有从它派生的类。

一件重要的事情
关于纯虚函数需要注意的是这些
必须在所有派生类中重写函数
否则编译会标记出错误。

简单例如,

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();
   }

We should use pure virtual function if we do not
want to instantiate a class but make it act as a base class
for all the classes that derive from it.

An important thing
to note about pure virtual functions is that these
functions must be overridden in all the derived classes
otherwise the compile would flag out an error.

Simple e.g,

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();
   }
吹泡泡o 2024-12-03 19:59:49

如果基类将方法定义为虚拟方法,但实现了空方法
主体也是如此,因此不需要派生类实现
身体,不应该清净吗?

这取决于你的设计。如果您的方法是纯虚拟的,您将向派生类开发人员发送一条消息,表示“您必须在此处放置一些实际代码,以便使您的类正常工作”。另一方面,如果您的方法是具有空主体的虚拟方法,则消息是“您可以在此处放置一些代码,但这取决于您的实际需要”。

virtual void AMethod1() {}                 // 1
virtual void AMethod2() {assert(false);}   // 2
virtual void AMethod3() = 0;               // 3

我肯定更喜欢选项 3 而不是 2,如果派生类没有实现虚拟方法,它将产生编译错误而不是运行时错误。

If a base class defines a method as virtual, but implements a empty
body as well, thus not requiring the derived classes from implementing
a body, should it not be made pure instead?

It depends on your design. If your method is pure virtual you are sending a message to the derived class developer that says 'you must place some actual code here so to make your class work'. On the other hand, if your method is virtual having an empty body, the message is 'you may place some code here, but its up to your actual needs'.

virtual void AMethod1() {}                 // 1
virtual void AMethod2() {assert(false);}   // 2
virtual void AMethod3() = 0;               // 3

I would definitely prefer option 3 over 2, it will yield a compilation error instead of a run-time error if derived class does not implement the virtual method.

倒带 2024-12-03 19:59:49

由于您需要虚拟机制;以下是我的简短回答:

(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

Since you need the virtual mechanism; following is my short answer:

(1) virtual void AMethod1() {}

Requirement:

- Allow creating objects of base class
- Base `virtual` method is use.

(2) virtual void AMethod2() {assert(false);}

Requirement:

- 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;

Requirement:

- Don't allow base class object creation
- Force derived classes to implement the method at compile time
小霸王臭丫头 2024-12-03 19:59:49

没有简单的规则:

如果对某些派生类有意义,则使用 1(空实现)
如果调用该函数则不执行任何操作。

如果派生类不实现 3 没有意义,则使用 3
功能。

在极少数情况下使用 2,该函数的前提条件是
另一个虚函数 hare 返回 true,并且该函数有一个
默认实现返回 false (或类似的内容)。
基本上,如果界面的一部分是可选的。 (但通常情况下,
在这种情况下最好派生一个接口;类实现
扩展接口源自它,并且客户端想要使用它
dynamic_cast 到扩展接口。)

根据经验(但你的编程风格可能不同),1 似乎适用于至少 90% 的时间,我认为在 C++ 的二十多年中,我'我用过 3 一次,或者两次。

There is no simple rule:

Use 1 (empty implementation) if it makes sense for some derived classes
to do nothing if the function is called.

Use 3 if it doesn't make sense for a derived class not to implement the
function.

Use 2 in the rare case where a precondition of the function is that
another virtual function hare returned true, and that function has a
default implementation to return false (or something along those lines).
Basically, if part of the interface is optional. (But usually, it's
better to derive an interface in such cases; classes implementing the
extended interface derive from it, and clients wanting to use it
dynamic_cast to the extended interface.)

From experience (but your programming style may be different), 1 seems to apply at least 90% of the time, and I think in over twenty years of C++, I've used 3 once, or maybe twice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文