虚函数陷阱和使用基函数
Virtual function pitfalls and using base functions
我一直在为虚函数编写一个参考的东西,因为我总是忘记它们是如何工作的。以下是目前为止的内容:
#include <iostream>
using namespace std;
struct Base
{
virtual void foo(int one = 1, int two = 2) = 0;
virtual Base* bar() { cout << "Base barn"; return this; }
virtual void baz(Base*) { cout << "Base bazn"; }
virtual void boo(Base*) { cout << "Base boon"; }
// Error: templates may not be virtual
//template <typename T> virtual T bad(T t) {return t}
virtual ~Base() {}
};
struct Derived : public Base
{
void foo(int one = 3, int two = 4)
{ cout << "one: " << one << " two: " << two << endl; }
Derived* bar() { cout << "Derived barn"; return this; }
void baz(Derived*) { cout << "Derived bazn"; }
using Base::boo;
void boo(Derived*) { cout << "Derived boon"; }
};
void example1()
{
Base* pB = new Derived();
Derived* pD = new Derived();
// Foo is called with default parameters based on pointer
pB->foo(); // one: 1 two: 2
pD->foo(); // one: 3 two: 4
// Bar is overridden because return type can be implicitly converted
pB->bar(); // Derived bar
pD->bar(); // Derived bar
// Baz is not overridden because parameters differ
pB->baz(pB); // Base baz
pB->baz(pD); // Base baz
//pD->baz(pB); // invalid conversion from Base* to Derived*
pD->baz(pD); // Derived baz
// Boo using test
pB->boo(pB); // Base boo
pB->boo(pD); // Base boo
pD->boo(pB); // Base boo
pD->boo(pD); // Derived boo
delete pB;
delete pD;
}
struct Base2
{
void foo(int one = 1, int two = 2) { foo_impl(one, two); }
virtual ~Base2() {}
private:
virtual void foo_impl(int one, int two) = 0;
};
struct Derived2 : public Base2
{
private:
void foo_impl(int one, int two)
{ cout << "one: " << one << " two: " << two << endl; }
};
void example2()
{
Base2* pB = new Derived2();
Derived2* pD = new Derived2();
// Now one set of default parameters exists
pB->foo(); // one: 1 two: 2
pD->foo(); // one: 1 two: 2
delete pB;
delete pD;
}
int main()
{
example1();
example2();
return 0;
}
我对boo()函数感到困惑。在我看来,pB->boo(pD)
接近example1()
的末尾应该调用函数的覆盖版本,但它调用基本版本。为什么?如果你能解释一下哪里需要所有的using
以及它是如何工作的,那将是有帮助的,谢谢。
另外,如果你在使用虚拟函数时想到了其他需要注意的陷阱,也可以把它们贴出来。谢谢。
可以从baz
函数中看到答案。正如您在评论中注意到的那样,派生类的baz
不会覆盖基类的版本,因为参数不同。boo
也是如此。
你的using Base::boo;
语句不会以任何方式改变boo
不覆盖。相反,它只是将基版本引入派生类的作用域。本质上,就好像派生类有两个函数的重载。
然而,对于pB->boo(pD);
,重载是不相关的,因为指针是根据Base
类型的。所以编译器只知道基类的boo
函数。因此,由于没有重写boo
,它最终调用基本版本。
相关文章:
- 防止在复制构造函数中隐式调用基构造函数
- 虚拟继承基构造函数消除
- 虚拟基类函数中派生类的大小
- 无法访问基类函数 C++
- 如何使派生类函数在调用时始终调用相同的基类函数?
- C++虚拟函数:基类函数是调用的,而不是派生的
- Qt基类函数定义
- 添加字符串类型的类成员会导致调用基类函数而不是子函数
- 继承基构造函数,基类是模板参数 (MSVC)
- 有没有办法调用基类函数,该函数在使用私有继承的派生类中被覆盖?
- 对基构造函数的条件调用
- C++ - 基类函数指针调用的替代方法
- 私有使用基构造函数的声明不是私有的
- 什么更有效率?在重载函数中或通过在基类函数中检查对象类型来实现
- 重载基类函数是不好的做法吗?
- C++ 继承基构造函数,但仍调用默认派生构造函数
- 在 qml 中公开基类函数
- 调用基类函数时强制使用类名?
- 派生类构造函数调用基构造函数
- 如何判断哪个派生的类对象称为基类函数