Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
纯虚函数实现 我正在读Scott Meyers的有效C++,我在继承这个章节。他说_C++_Inheritance_Definition_Virtual Functions_One Definition Rule - Fatal编程技术网

纯虚函数实现 我正在读Scott Meyers的有效C++,我在继承这个章节。他说

纯虚函数实现 我正在读Scott Meyers的有效C++,我在继承这个章节。他说,c++,inheritance,definition,virtual-functions,one-definition-rule,C++,Inheritance,Definition,Virtual Functions,One Definition Rule,纯虚函数只指定接口的继承 简单(不纯)虚函数指定接口的继承 加上默认实现的继承 现在,考虑下面两个类: struct A { virtual void foo() = 0; }; void A::foo(){ std::cout << "Default foo" << std::endl; } struct B : A{ virtual void foo(){ A::foo(); std::cout << "Derived foo" <

纯虚函数只指定接口的继承

简单(不纯)虚函数指定接口的继承 加上默认实现的继承

现在,考虑下面两个类:

struct A {
    virtual void foo() = 0;
};

void A::foo(){ std::cout << "Default foo" << std::endl; }

struct B : A{
    virtual void foo(){ A::foo(); std::cout << "Derived foo" << std::endl; }
};
如果我不按如下方式定义不纯的虚函数:

struct A {
    virtual void foo();
};



struct B : A{
    virtual void foo(){ std::cout << "Derived foo" << std::endl; }
};
结构A{ 虚拟void foo(); }; 结构B:A{
虚拟void foo(){std::cout纯虚函数不仅使基类不可实例化,而且强制所有派生类实现相应的虚函数。如果不使基类纯虚,则派生类可能选择不实现它。定义纯虚函数是可以的,只要您正如Scott Meyers指出的那样,它从一个派生实例中使用它,并提供了一个可以作为默认值使用的实现

请注意,您的演示并不像您想象的那样工作。如果您在使用多态性时执行通常被视为常见的操作

A* p = new B; // or, std::unique_ptr<A> p = make_unique<B>();
p->foo();
A*p=new B;//或者,std::unique\u ptr p=make_unique();
p->foo();
然后会出现严重的链接器错误:

架构x86_64的未定义符号:

“A的类型信息”,引用自: ccoVYpAI.o中B的类型信息


选择所谓的默认实现仍然需要派生类显式地执行此操作。如果通过基类引用/指针调用
foo
,则您的演示会失败。使用gcc编译总是导致链接器错误,而使用clang编译则取决于优化级别。@stella,也不在不纯虚拟函数中。如果使用派生类类想要使用基类实现,它不能简单地提供重写函数。这并不是说它可以隐式地使用基类实现作为其自身实现的一部分,而是通过选择默认实现,我指的是整个实现。“我们仍然可以像我在示例中所做的那样为纯虚拟函数提供默认实现,并通过…”调用它-如果它是“默认实现”"您不需要显式调用它。它只是一个实现——C++可以方便地使用相同的函数名,因此它可以是对开发派生类的一个提示,它可以为自己的实现提供有用的支持函数,但是如果基类不能实现纯的虚拟化,则不会有任何实际的区别。并且可能提供一个不同名称的支持函数。上一个示例导致未定义的行为(无需诊断):由于
a::foo()
未标记为
=0;
,因此它必须在某个位置具有主体(即使从未调用)。
A* p = new B; // or, std::unique_ptr<A> p = make_unique<B>();
p->foo();