我有一个带有可选虚函数的基类
class Base {
virtual void OnlyImplementThisSometimes(int x) {}
};
当我编译它时,我得到一个关于未使用的param 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 ++中常见的陷阱还是我误解了虚函数?
答案 0 :(得分:22)
忽略设计问题,您可以通过省略变量名来解决编译器有关未使用变量的警告,例如:
virtual void OnlyImplementThisSometimes(int ) { }
在尝试覆盖虚函数时错误地实现了错误的方法签名只是在C ++中需要注意的事情。 C#等语言使用'override'关键字来解决这个问题。
答案 1 :(得分:11)
我们将宏_unused
定义为:
#define _unused(x) ((void)x)
然后将函数定义为:
virtual void OnlyImplementThisSometimes(int x) { _unused( x );}
这不仅让编译器不抱怨,而且让任何维护代码的人都明白你没有忘记x - 你故意忽略它。
答案 2 :(得分:6)
为什么要在基类中定义它?如果基类不打算使用该方法,那么只需在派生类中将其定义为虚方法即可。
或者默认实现可能会抛出异常
答案 3 :(得分:4)
如果提供虚函数的默认实现,则对于不覆盖该函数的所有派生类,它应该是正确的实现。如果你不能提供正确的实现,那么我的建议是创建一个纯虚函数,并将其留给派生类来提供实现。不允许调用该方法的派生类可以抛出异常,以确保不会错误地使用它。
答案 4 :(得分:3)
除了简单地省略变量名之外,在许多编译器中你可以告诉编译器,你知道它是未使用的并且通过这样做来SHUTUP
int func(int x)
{
(void) x;
}
答案 5 :(得分:2)
这在我的代码中有点常见。例如,我有专为单线程操作和多线程设计的类。有很多常见的例程和数据。我把所有这些都放在了基类中(它有几个纯虚拟的)。
我在基类中实现了两个空虚函数:Init()和Cleanup()。单线程派生类不会实现它们,但是多线程派生类会这样做。
我有一个工厂函数创建approprite派生类然后返回一个指针。客户端代码只知道基类类型,它调用Init()和Cleanup()。这两种情况都是正确的。
当然,关于如何做到这一点可能还有其他很好的建议,但这个习惯用法很适合我的很多代码。
答案 6 :(得分:2)
这不是一个糟糕的做法,它是指定一个可选择实现的类的部分的常用习惯。
目前我正在将它用于用户输入系统,因为对于该类的用户来说实现每一种方法都是单调乏味的,即使他最有可能也不会使用它。
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) {}
};
答案 7 :(得分:2)
顺便说一下,如果你知道你的基类,那么从来没有必要做动态 up -casts,即从派生到基础。
Base *b = &d;
同样会这样做,dynamic_cast<>
应该在您向下投射时使用,即从基础到派生:
if((Derived *d = dynamic_cast<Derived *>(b)) != 0)
{
// use d
}
(当然,在向下投射的情况下,static_cast<>
通常也会有用。)
答案 8 :(得分:-1)
试试这个:
class Base {
virtual void OnlyImplementThisSometimes(int x) = 0;
};
我已经做了类似的事情已经有一段时间了,但我相信这就是你宣布虚拟功能的方式。
正如其他人所说,变量名在像这样的函数声明中是可选的。
答案 9 :(得分:-2)
最简单的答案如下所示:
class Base {
virtual void OnlyImplementThisSometimes(int x) { x;}
};
对绝对没有任何作用的变量的简单引用将删除所有警告(无论如何都来自最高级别的VC ++)。