gpt4 book ai didi

c++ - 在这些情况下,标准中的哪个地方需要转发到基类?

转载 作者:搜寻专家 更新时间:2023-10-31 01:59:33 25 4
gpt4 key购买 nike

也许更好的是:为什么标准要求在这些情况下转发到基类? (是的是的是的 - 为什么? - 因为。)

class B1 {
public:
virtual void f()=0;
};
class B2 {
public:
virtual void f(){}
};
class D : public B1,public B2{
};
class D2 : public B1,public B2{
public:
using B2::f;
};
class D3 : public B1,public B2{
public:
void f(){
B2::f();
}
};
D d;
D2 d2;
D3 d3;

MS 给出:

sourceFile.cpp
sourceFile.cpp(24) : error C2259: 'D' : cannot instantiate abstract class
due to following members:
'void B1::f(void)' : is abstract
sourceFile.cpp(6) : see declaration of 'B1::f'
sourceFile.cpp(25) : error C2259: 'D2' : cannot instantiate abstract class
due to following members:
'void B1::f(void)' : is abstract
sourceFile.cpp(6) : see declaration of 'B

对于 MS 编译器也是如此。

可能买第一个箱子,D。但是在 D2 中 - f 是由 using 声明明确定义的,为什么这不足以让编译器被要求填写 vtable?

标准中哪里定义了这种情况?

添加到回复中

关于我接受的以下答案:

为什么这在规范中看起来不是错误? - 如果一个人有一个包含一系列非虚拟 f() 的继承层次结构,它们在派生类中的使用由 using 语句确定,并且将基类中 f 的 decl 更改为虚拟,那么这可以改变哪个在派生类中调用 f 时使用 using 语句来选择它们的 f。这是一个我不知道的 C++“陷阱”。它可能是语言的一部分,但这种“远距离行动”让我感到不安,对我来说似乎违反了某种正确性/维护原则(我现在无法完全表述)。

但我可以举个例子:

#include <iostream>
using std::cout;


namespace NonVirtual_f{

class C0 {
public:
void f(){cout<<"C0::f()"<<'\n';}
};

class C1 : public C0{
public:
void f(){cout<<"C1::f()"<<'\n';}
};

class C2 : public virtual C1{
public:
void f(){cout<<"C2::f()"<<'\n';}
};

class D3 : public virtual C1, public C2{
public:
using C1::f;
};


}//namespace NonVirtual_f

namespace Virtual_f{


class C0 {
public:
virtual void f(){cout<<"C0::f()"<<'\n';}
};

class C1 : public C0{
public:
void f(){cout<<"C1::f()"<<'\n';}
};

class C2 : public virtual C1{
public:
void f(){cout<<"C2::f()"<<'\n';}
};

class D3 : public virtual C1, public C2{
public:
using C1::f;
};



}//namespace Virtual_f




int main(int argc,const char* const*argv){

NonVirtual_f::D3 nv3;
nv3.f();

Virtual_f::D3 v3;
v3.f();

return 0;
}

从哪里输出:

C1::f()
C2::f()

改变的只是C0中f的虚性。特别是一旦选择了基类中 f 的非虚拟性,如果某些派生类(通常不能知道),则不能在没有维护问题的情况下更改它about) 已被“覆盖”,如上例所示。

如果您反对“好吧,不要在非虚拟情况下重写这种方式”,我同意这是不好的做法,但这似乎不止于此。对我来说,语言应该:

不允许在 NonVirtual::D3 中使用(目前不可能,因为可能有其他重载的 f 引入 [除非在函数案例中使用允许的签名])

完全禁止使用函数语句并强制转发

在所有情况下都使用实际覆盖

允许一些函数的语法声明(本质上是一个函数使用),如:

void f(*signature*) = C2::f;

我到底错过了什么?有人可以想出一个场景来阐明标准中这种选择的“原因”吗?

最佳答案

C++ 标准在 §10.3/2 中说:

The rules for member lookup (10.2) are used to determine the final overrider for a virtual function in the scope of a derived class but ignoring names introduced by using-declarations.

因此,即使您使用 using B2::f;B2::f() 带入派生类,也不会考虑覆盖 B1::f().

因此,D2 是抽象的,因为 §10.4/4:

A class is abstract if it contains or inherits at least one pure virtual function for which the final overrider is pure virtual.

关于c++ - 在这些情况下,标准中的哪个地方需要转发到基类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2933504/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com