English 中文(简体)
非纯虚函数带参数是不好的编程实践吗?
原标题:
  • 时间:2008-11-03 23:56:21
  •  标签:

我有一个基类,其中包含一个可选的虚函数。

class Base {
    virtual void OnlyImplementThisSometimes(int x) {}
};

当我编译这个时,我收到一个有关未使用参数 x 的警告。我应该如何实现虚函数?我已经将其重写成这样:

class Base {
    virtual void OnlyImplementThisSometimes(int x) 
    {
        x = 0;
    }
};

我也有一个问题,如果我不仔细,我创建的子类可能会实现错误的函数,然后由于重载,我可能没有注意到:例如。

class Derived : public Base {
    void OnlyImplementThisSometimes(int x, int y) { // some code }
};

Derived d;
Base *b = dynamic_cast<Base *>(&d);
b->OnlyImplementThisSometimes(x); // calls the method in the base class

基类方法被调用是因为我使用了一个“int y”参数实现了派生函数,但没有关于此的警告。这些只是C++中的常见陷阱,还是我误解了虚函数?

最佳回答

忽略设计问题,您可以通过省略变量名称来解决编译器关于未使用变量的警告,例如:

virtual void OnlyImplementThisSometimes(int ) { }

在尝试覆盖虚函数时错误实现错误的方法签名只是你需要在 C++ 中小心的事情。像 C# 这样的语言通过 override 关键字回避了这个问题。

问题回答

我们定义一个宏_unused如下:

#define _unused(x) ((void)x)

然后定义这个函数为:

virtual void OnlyImplementThisSometimes(int x) { _unused( x );}

这不仅可以避免编译器抱怨,而且对于任何维护代码的人来说,都很明显你没有忘记x--你是故意忽略它的。

为什么要在基类中定义它?如果基类不会使用该方法,那么可以在派生类中将其定义为虚拟方法。

或者默认实现可以抛出异常。

如果您提供一个虚函数的默认实现,它应该是所有未覆盖该函数的派生类的正确实现。如果您无法提供一个正确的实现,则我的建议是制作一个纯虚函数,并将其交给派生类来提供实现。不允许调用该方法的派生类可以抛出异常以确保它不被错误使用。

除了简单地省略变量名称外,在许多编译器中,你可以通过这样告诉编译器,你已经知道它没有被使用并且闭嘴

int func(int x)
{
   (void) x;
}

这在我的代码中有点常见。例如,我有设计用于单线程操作和多线程的类。有许多共同的程序和数据。我把所有的东西都放在基类中(它还有一些纯虚函数)。

我在基类中实现了两个空的虚函数:Init()和Cleanup()。单线程派生类不实现它们,但多线程派生类会实现。

我有一个工厂函数,创建适当的派生类然后返回指针。客户端代码只知道基类类型,并调用Init()和Cleanup()。两种情况都做得正确。

当然,也许有其他好的建议如何做到这一点,但这个成语对我的很多代码都很有效。

这并不是一种不好的做法,而是一种常见的习语,用于指定类的某些部分是可选实现的。

目前我正在使用它作为用户输入系统,因为对于那个类的用户来说,实现每个方法可能会很繁琐,即使他很可能不会使用它。

class mouse_listener{
public:
    virtual ~mouse_listener() {}

    virtual void button_down(mouse_button a_Button) {}
    virtual void button_up(mouse_button a_Button) {}
    virtual void scroll_wheel(mouse_scroll a_Scroll) {}
    virtual void mouse_move_abs(math::point a_Position) {}
    virtual void mouse_move_rel(math::point a_Position) {}
};

顺便说一句,如果你知道你的基类,就不需要进行动态向上转型,即从派生类到基类。

Base *b = &d;

同样可以做到,但当您进行向下转换时(即从基类向派生类),应使用dynamic_cast<>

if((Derived *d = dynamic_cast<Derived *>(b)) != 0)
{
  // use d
}

当然,在 down-cast 的情况下,static_cast 将通常同样适用。

请尝试这个:

class Base {
    virtual void OnlyImplementThisSometimes(int x) = 0;
};

这样做已经有一段时间了,但我相信这就是声明虚函数的方式。

正如其他人所说,变量名在这样的函数声明中是可选的。

最简单的答案如下所示:

class Base {
    virtual void OnlyImplementThisSometimes(int x) { x;}
};

对完全不起作用的变量的简单引用将消除所有警告(无论在最高级别的VC ++中)。





相关问题
热门标签