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派生了的实现,两条语句都不编译 为什

C++

给定一个基类
base
和一个派生类
derived
,由
derived
的构造函数构造的第一件事就是
base
子对象。因为它被称为子对象,所以我假设它可以像任何其他成员对象一样,通过在
派生的
对象上使用点运算符从客户机代码访问。我还假设它可以通过
this->Base
派生的
实现代码访问。完全由已初始化的对象的名称后跟分号组成的语句应编译,但也无效。按照这个逻辑,给定一个
Derived
对象
myderived
,我尝试:
myderived.Base
this->Base中的code>派生了
的实现,两条语句都不编译

为什么??我知道
Base
本身就是
Base
类的名称,而不是
Base
对象的名称。但是我认为
Base
是由
myderived.
(客户端代码)或
这个->
(实现代码)前缀指的是基子对象,因为
Base
没有任何前缀限定,是
Derived
的构造函数初始值设定项中引用
Base
子对象的方式。请参阅下面的代码,这些代码(将代码注释掉)适用于VC12和g++4.8
Derived
扩展了
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我同意,它实际上写得很好,并且有条理地呈现,阅读几乎是作为一个一步一步的分析和指导。考虑到你(显然)是我没有被要求这么做。所以,我可以收回这次收到的仅有的两张赞成票中的一张?如果我有能力和深入的知识来回答你的长篇大论,我会的。我发现它……幽默……最终是一份关于查名规则和规定的摘要的泛音的长度和细节,如果这是我想要的被告我只能接受