C++ 用于访问基本子对象的点或箭头运算符与范围分辨率运算符
C++ 给定一个基类C++ 用于访问基本子对象的点或箭头运算符与范围分辨率运算符,c++,inheritance,namespaces,scope-resolution,dot-operator,C++,Inheritance,Namespaces,Scope Resolution,Dot Operator,C++ 给定一个基类base和一个派生类derived,由derived的构造函数构造的第一件事就是base子对象。因为它被称为子对象,所以我假设它可以像任何其他成员对象一样,通过在派生的对象上使用点运算符从客户机代码访问。我还假设它可以通过this->Base从派生的实现代码访问。完全由已初始化的对象的名称后跟分号组成的语句应编译,但也无效。按照这个逻辑,给定一个Derived对象myderived,我尝试:myderived.Base和this->Base派生了的实现,两条语句都不编译 为什
base
和一个派生类derived
,由derived
的构造函数构造的第一件事就是base
子对象。因为它被称为子对象,所以我假设它可以像任何其他成员对象一样,通过在派生的
对象上使用点运算符从客户机代码访问。我还假设它可以通过this->Base
从派生的实现代码访问。完全由已初始化的对象的名称后跟分号组成的语句应编译,但也无效。按照这个逻辑,给定一个Derived
对象myderived
,我尝试:myderived.Base客户代码中的代码>和this->Base中的code>派生了
的实现,两条语句都不编译
为什么??我知道Base
本身就是Base
类的名称,而不是Base
对象的名称。但是我认为Base
是由myderived.
(客户端代码)或这个->
(实现代码)前缀指的是基子对象,因为Base
没有任何前缀限定,是Derived
的构造函数初始值设定项中引用Base
子对象的方式。请参阅下面的代码,这些代码(将代码注释掉)适用于VC12和g++4.8Derived
扩展了Base
和Derived
的定义声明了Base
数据成员membase
,因此我的Derived
对象应该包含两个Base
对象。假设成功的编译不是任何编译器标准不一致的结果,控制台输出(在注释中)为两个不同的Base
对象的int
成员n
显示不同的值,这意味着在派生的的ctor初始值设定项中,Base
指继承的Base
子对象,而membase
指声明的数据成员对象。在Derived
的ctor初始值设定项中,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"
}
#包括
结构基{
基数(整数par):n(par){}
void foo(){std::cout
不可以,您可以有一个名为Base
的成员,该成员与Base
子对象分开。:
标点符号将名称解析限制为忽略成员对象名称
参见#1。通常答案是否定的,因为你会疯狂地故意让一个成员别名一个基。但是,在模板中,类可能不知道其基的名称
否。成员子对象和基础子对象都是子对象,但访问方式不同
它总是引用类,并且名称Base
本身继承自Base
。如果您有一个疯狂的成员别名,那么您需要使用对Base
的其他引用,例如命名空间限定id
static\u cast (派生对象)
否,::
的优先级高于
,因此在myderived
中查找Base::foo
成员,然后应用函数调用运算符。但是(Base::foo)周围不允许使用参数
,因为:
不是生成子表达式的运算符;这就是为什么我更喜欢称它为标点符号
参见#6.myderived.Base
本身并不是什么,因为在
之前带有:
的基组
是的。请注意,类不是名称空间;它们是不同的东西,两者碰巧使用相同的范围表示法
<>这似乎是解释C++在其他语言中的应用。例如,在爪哇中,类是一个具有自己数据成员的对象。在C++中,代码>静态< /COD>类成员和命名空间成员是完全分离的对象,可以在任何地方定义。
Base::Base::Base::
之所以有效,是因为类的名称被注入自身,就好像它是一个成员typedef
。VC可能会出错,并将其解释为对构造函数的引用。根据规范,特殊的typedef(称为注入的类名)指特殊情况下的构造函数,但之前的范围运算符不是这样的情况
每个类本身都包含一个隐式的typedef
前缀::
本身并不是全局名称空间的名称,而只是语法中的一个特例,以弥补其缺少名称。同样,无论好坏,您都不能声明
namespace global = :: ; // error: :: alone does not name anything.
我不会“翻查”任何人的问题,尽管我会翻查一些人的答案,因为这个网站上有一小群才华横溢的人,你永远都不会停止学习。如果你发布了它,你这么做的目的不是为了做你现在说不给任何人(包括你自己)的事情吗问?也就是说,读它?@WhozCraig呃,它很长,但有一个中心论点。答案随着问题的发展而流动。@Potatoswatter我同意,它实际上写得很好,并且有条理地呈现,阅读几乎是作为一个一步一步的分析和指导。考虑到你(显然)是我没有被要求这么做。所以,我可以收回这次收到的仅有的两张赞成票中的一张?如果我有能力和深入的知识来回答你的长篇大论,我会的。我发现它……幽默……最终是一份关于查名规则和规定的摘要的泛音的长度和细节,如果这是我想要的被告我只能接受