是带有参数的非纯虚拟函数的不良做法
Are non-pure virtual functions with parameters bad practice?
我有一个带有可选虚拟函数的基类
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"param实现了派生函数,但没有任何警告。这些只是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) {}
};
Btw,如果你知道你的基类,就永远不需要进行动态的up-转换,即从派生到基类。
Base *b = &d;
也可以,当你下投时,应该使用dynamic_cast<>
,即从基础到衍生:
if((Derived *d = dynamic_cast<Derived *>(b)) != 0)
{
// use d
}
(当然,在向下投射的情况下,static_cast<>
通常也能工作。)
试试这个:
class Base {
virtual void OnlyImplementThisSometimes(int x) = 0;
};
我已经有一段时间没有做过这样的事情了,但我相信这就是你声明虚拟函数的方式。
正如其他人所说,在这样的函数声明中,变量名是可选的。
最简单的答案如下所示:
class Base {
virtual void OnlyImplementThisSometimes(int x) { x;}
};
对变量的简单引用绝对不起任何作用,将删除所有警告(无论如何都是从VC++的最高级别)。
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 删除复制构造函数的 Intel 13.1.2 中不良C++行为的解决方法
- 不从成员函数C 存储返回值认为不良习惯
- 正在(在构造函数中)将其包含一个不良设计的指针传递,如果是的,则解决方案是什么
- 在模板类 T> 的函数中使用指向类 T 成员的函数指针作为参数的不良做法
- 内存管理不良?类成员(布尔值)值大于 1,在递归函数中
- 对所有成员函数和属性使用 "this" 是否是一种不良做法?
- 从对象的方法或其他类构造函数中删除对象是否被视为不良做法?
- 通过函数指针从外部文件调用静态函数的不良做法
- 是带有参数的非纯虚拟函数的不良做法