我的基本理解是,纯虚函数没有实现,但我被告知可能会有纯虚函数的实现。
class A {
public:
virtual void f() = 0;
};
void A::f() {
cout<<"Test"<<endl;
}
上面的代码是否正确?
将一个纯虚函数定义为带有实现的函数有什么目的?
我的基本理解是,纯虚函数没有实现,但我被告知可能会有纯虚函数的实现。
class A {
public:
virtual void f() = 0;
};
void A::f() {
cout<<"Test"<<endl;
}
上面的代码是否正确?
将一个纯虚函数定义为带有实现的函数有什么目的?
一个纯虚函数必须在将直接实例化的派生类型中实现,但是基类仍然可以定义实现。如果访问权限允许,派生类可以使用完全作用域名称(例如,在您的示例中调用 A::f()
- 如果 A::f()
为 public
或 protected
)来显式调用基类实现。如下所示:
class B : public A {
virtual void f() {
// class B doesn't have anything special to do for f()
// so we'll call A's
// note that A's declaration of f() would have to be public
// or protected to avoid a compile time problem
A::f();
}
};
明确一点,你误解了在虚函数后面使用 = 0 的含义。
= 0 表示派生类必须提供实现,而不是基类不能提供实现。
在实践中,当你将虚函数标记为纯虚函数(=0)时,提供定义很少有意义,因为除非有人通过 Base::Function(...) 明确调用它或者基类构造函数调用所涉及的虚函数,否则它永远不会被调用。
class Base {
public:
virtual ~Base() = 0;
};
Base::~Base() {}
class Derived : public Base {};
int main() {
// Base b; -- compile error
Derived d;
}
它的优势在于强制子类型仍需重写该方法,但也提供了默认或附加实现。
带或不带函数体的纯虚函数意味着派生类型必须提供自己的实现。
在基类中使用带有函数体的纯虚函数是有用的,如果您的派生类想要调用基类的实现。
是的,这是正确的。在你的例子中,从A派生的类继承了接口f()和默认实现。但你强制要求派生类实现方法f()(即使只是调用A提供的默认实现)。
斯科特·迈耶斯在他的书《Effective C++(第二版)》中讨论了这个问题,第36条是区分接口继承和实现继承。最新版可能会有所改变。
class A
{
public:
virtual void foo()=0;
virtual void bar();
}
class B : public virtual A
{
public:
void foo() { bar(); }
}
class C : public virtual A
{
public:
void bar();
}
class D : public B, public C
{}
int main(int argc, const char* argv[])
{
A* obj = new D();
**obj->foo();**
return 0;
}
C
的对象。你可以实例化一个类型为 D
的对象,因为它从 B
中获得了 foo
的实现。 - YoungJohnclass Animal
{
public:
virtual void sound() = 0;
}
class Dog : public Animal
{
public:
void sound()
{
std::cout << "Meo Meo";
}
}
Animal::sound()
的意义是什么。 - Burak在编程中,一个重要的应用场景是拥有带有实现体的纯虚方法,当你想要创建一个抽象类,但是在类中没有适合做成纯虚方法的方法时,你可以将类的析构函数设置为纯虚方法,并为其提供所需的实现(即使是空实现)。例如:
class Foo
{
virtual ~Foo() = 0;
void bar1() {}
void bar2(int x) {}
// other methods
};
Foo::~Foo()
{
}
这种技术使得Foo
类成为抽象类,因此无法直接实例化该类。同时,您没有添加额外的纯虚方法来使Foo
类成为抽象类。