C++
给定一个基类Base
和一个派生类Derived
,由 的构造函数构造的第一件事Derived
就是Base
子对象。由于它被称为子对象,我假设它可以像任何其他成员对象一样通过在Derived
对象上使用点运算符从客户端代码访问。我还假设它可以Derived
通过this->Base
. 完全由已初始化的对象名称后跟分号组成的语句应该可以编译,但也没有效果。按照这个逻辑,给定一个Derived
object myderived
,我尝试了:myderived.Base;
在客户端代码和this->Base;
inDerived
的实现中,并且两个语句都没有编译。
为什么?我知道Base
,它本身是Base
类的名称,而不是Base
对象的名称。但我认为(客户端代码)或(实现代码)前缀Base
限定是指基本子对象,因为没有任何前缀限定,是在构造函数初始化程序中引用子对象的方式。请参阅下面的代码,该代码(除了注释掉的代码)适用于 VC12 和 g++ 4.8。extends and的定义声明了一个数据成员,所以我的对象应该包含两个myderived.
this->
Base
Base
Derived
Derived
Base
Derived
Base
membase
Derived
Base
对象。假设成功编译不是任何编译器标准不一致的结果,控制台输出(在注释中)显示两个不同对象的int
成员的不同值,这意味着 in的 ctor 初始化程序是指继承的子对象,而引用声明的数据成员对象。In的 ctor 初始化器,专门指继承的子对象,而不仅仅是任何对象或类。n
Base
Derived
Base
Base
membase
Derived
Base
Base
Base
#include <iostream>
struct Base {
Base(int par) : n(par) {}
void foo() { std::cout << "Base: " << n << std::endl; }
int n;
};
struct Derived : Base {
Derived() : Base(2), membase(3) {}
Base membase;
void foo() { std::cout << "Derived: " << n << std::endl; }
// void g() { this->Base; } // Error in VC12 & g++ 4.8
// ^ VC12: error C2273: 'function-style cast' : illegal as
// right side of '->' operator
};
int main() {
Derived myderived;
// myderived.Base; //Error in VC12 & g++ 4.8
// ^ VC12: error C2274: 'function-style cast' : illegal as
// right side of '.' operator
myderived.foo(); // OUTPUT: "Derived: 2"
myderived.Base::foo(); // OUTPUT: "Base: 2"
myderived.membase.foo(); // OUTPUT: "Base: 3"
}
同样,不应该
myderived.Base;
或this->Base;
唯一地引用继承的Base
子对象并编译?Base
inmyderived.Base
或this->Base
引用Base
子对象或Base
类或任何东西?一般来说,继承的基础子对象是否被视为派生类的数据成员?
从 的角度来看
Derived
,是否只引用了构造函数初始化器Base
上下文中的继承子对象,而只引用了 ctor 初始化器之外的类?Derived
Base
Derived
如何
Base
通过对象访问继承的子对象,如在的实现代码和客户端代码Derived
中如何表达“对象的继承Base
子Derived
对象” ?Derived
范围解析运算符 in 的使用
myderived.Base::foo()
,其中foo()
的方法是Base
,编译。这是否意味着Base
是 的数据成员myderived
,因为它由myderived
点运算符限定?如果是这样,那是Base
类Base
还是Base
子对象?但
myderived.Base.foo()
不编译。对象成员的 AFAIK 访问在客户端代码中由对象名称和点运算符限定。由范围解析运算符而不是对象名称和点运算符限定的两种事物是(a)对属于命名空间的任何事物的外部访问和(b)静态数据成员的名称和成员函数的名称在其类定义之外定义的定义,在这种情况下Base
,在 之前的::
指的是Base
类,而不是任何Base
实例。这是否意味着Base
inmyderived.Base
是命名空间或引用类?如果是这样,那么它是命名空间还是引用该类取决于它是否附加了一个
::
后跟的成员Base
?如果#7 的答案是肯定的,那为什么?这似乎与以下逻辑不协调:命名空间对一个变量的封闭本身并不使命名空间能够封闭或构造该变量类型的其他实例。命名空间只拥有该类型的一个实例——它包含的变量。作为类的一部分的成员也是如此,例如静态数据成员。该类只拥有该类型的一个实例——它包含的静态数据成员。相反,一个类的同名非静态数据成员与该类的实例一样多。
给定方法
h()
和对象,在 VC12 和 g++ 4.8 中编译。此外,g++ 4.8 可以在该语句中采用任意数量的额外s,例如. 这样的说法似乎暗示是. 但 VC12 给. 但是给定object ,VC12 编译得很好,这也意味着 VC12 可以将一个类视为其自身的成员。但这与其无法编译先前的声明相矛盾。此外,VC12 无法编译具有任意数量额外内容的任何版本Base
Derived
myderived
myderived.Base::h();
Base::
myderived.Base::Base::h();
Base
Base
error C3083: '{ctor}': the symbol to the left of a '::' must be a type
Base
mybase
mybase.Base::h();
mybase.Base::h();
Base::
s(例如mybase.Base::Base::h()
)的任何版本,但 g++ 可以。哪个编译器是正确的,如果有的话?无论如何,这是否意味着命名空间或类可以包含自身?给定一个全局
int
变量x
,该语句::::x;
(带有两个范围解析运算符)不会在任一编译器中编译,所以我假设全局范围不包含全局范围。