C++ 什么';在C+中,类型和名称之间的区别是什么+;?

C++ 什么';在C+中,类型和名称之间的区别是什么+;?,c++,c++11,types,C++,C++11,Types,我正在阅读,我在这个问题的代码中添加了一个构造函数,如下所示 class Foo { struct Bar { int i; Bar(int a = 5) :i(a) {}; }; public: Bar Baz() { return Bar(); } }; int main() { Foo f; // Foo::Bar b = f.Baz(); // error auto b = f.Baz();

我正在阅读,我在这个问题的代码中添加了一个构造函数,如下所示

class Foo {
    struct Bar { 
        int i; 
        Bar(int a = 5) :i(a) {}; 
    };

  public:
    Bar Baz() { return Bar(); }
};

int main() {
    Foo f;
    // Foo::Bar b = f.Baz();  // error
    auto b = f.Baz();         // ok
    std::cout <<"b.i="<< b.i<<endl;
    return 0;
}
  • 如果我添加
    typedef条B
    Foo
    的公共部分,以下内容之间有什么区别

     Foo::Bar b = f.Baz();
     Foo::B   b = f.Baz(); 
    
  • 场景1和场景2之间是否存在差异

    类型和名称之间有什么区别

    类型没有、有一个或多个名称。Typedef只是为类型创建新名称的一种方法

    public
    private
    关键字与名称相关,而与基础类型或成员无关

    为了显式声明特定类型的对象,您需要该类型的名称<代码>自动不需要这个。例如,如果使用未命名的类,则该类没有名称,但仍可在其上使用auto

    一个类型最多只能有一个“”。即使通过typedef或别名使用它,编译器也会在这个名称下使用它(或者实际上是这个名称的原始版本)。因此:

    如果不使用auto或decltype,就无法创建变量
    f
    。因为它的类型没有名字。没有名称的类型的另一个示例

    struct foo
    {
        struct{
            int x;
            int y;
        } memberVar;
    };
    
    将允许您执行以下操作:

    foo bar;
    
    auto baz = bar.memberVar;
    
    std::cout << baz.x;
    
    打印“int”

    注意事项:

    • 我避免使用alias作为对象其他名称的指示符,因为这可能会导致与alias关键字混淆

    • 这大部分是我从经验中得到的。所以我可能错过了一些片段

    • 由于缺少一个更好的词,我用了“真名”这个词。如果有人知道官方的说法或更好的说法,我很乐意听到:)


    您链接的问题解释了很多,但作为对那里所写内容的补充

  • 主要区别在于,在第二行
    autob=…
    中,您让编译器推断表达式的类型。无法指定类型,因为类型的名称已隐藏。但类型是可用的(至少从编译器)

  • 您可以公开类型的名称,以便可以使用它

  • 这是一个很好的答案

    <> >尝试回答标题中的问题,您可以将类型视为形状,并将类型的名称视为用于引用特定形状的名称。即使“形状”的名称被隐藏,形状仍然存在并且可以使用。

    [前面有一些标准]

    让我们同意
    auto
    演绎的工作方式与模板参数演绎的工作方式相同:

    [dcl.spec.auto]/p7

    如果占位符是自动 类型说明符,使用模板参数推断规则确定推断的类型

    模板在编译过程中会受到影响。在第一阶段,访问控制应用于名称查找

    [basic.lookup]/p1

    重载解析(13.3)在名称查找成功后进行。只有在名称查找和函数重载解析(如果适用)成功后,才会考虑访问规则(第11条)。只有在名称查找、函数重载解析(如果适用)和访问检查成功后,才能在表达式处理中进一步使用名称声明引入的属性

    auto
    decltype(auto)
    通常是推断类型的占位符,[temp.arg]/p3确实表示

    模板参数的名称应可在用作模板参数的位置访问

    但是这里不涉及名称,只涉及类型。访问控制适用于名称,一个类型可以映射为0、1或多个名称,这就是在上面的代码中使用
    auto
    时要处理的问题:它在语义上等同于模板推断的语义,这是经过设计的

    [class.access]/p4

    访问控制统一应用于所有名称,无论这些名称是从声明中引用的还是从 表达。[……]无障碍 不考虑typedef所指实体的名称。比如说

    为了让自己相信以下内容,请看一看包含模板参数推断的相同代码(概念上等同于
    auto
    version)

    模板
    T推断(T){
    返回t;
    } 
    福班{
    结构条{
    int i;
    Bar(inta=5):i(a){};
    };
    公众:
    Bar*getB(){返回新的Bar(5);}//泄漏,为了清晰起见并不重要
    };
    int main(){
    福福;
    
    std::我可以说没有私有类型。只有私有成员,这只意味着它们的名称是不可访问的。类型本身不受访问控制。dyp是对的,名称和类型是两个不同的东西,在编译过程中处理方式不同phases@laurisvr,你能给我一个前男友吗这个类型的例子中没有命名的联盟吗?是这个例子中的未命名的联盟吗?是<代码> int >代码>被认为是<代码> int <代码>的类型吗?@ @ ALANQUUNZI我已经编辑了我的帖子以包含一些例子。并且进一步阐述了命名的工作原理。请注意C++禁止在返回或参数中定义新的类型。类型,如中所述。但是,还有其他一些方法可以创建返回未命名类型的函数。(我将在几分钟内添加其中一些。)@dyp“有些编译器适用于int为16位的体系结构。”你是对的。我的遗漏很愚蠢。我已经相应地更新了答案。
    auto f = [] () -> struct {int x, y ; } { return { 99, 101 } ; } ;
    
    struct foo
    {
        struct{
            int x;
            int y;
        } memberVar;
    };
    
    foo bar;
    
    auto baz = bar.memberVar;
    
    std::cout << baz.x;
    
    std::cout << typeid(int32_t).name(); 
    
    class A {
      class B { };
    public:
      typedef B BB;
    };
    void f() {
      A::BB x; // OK, typedef name A::BB is public
      A::B y; // access error, A::B is private
    }
    
    template<class T> 
    T deduce(T t) {
        return t;
    } 
    
    class Foo {
        struct Bar{ 
            int i; 
            Bar(int a = 5):i(a){}; 
        };
    public:
    
      Bar *getB() { return new Bar(5); } // Leaks, doesn't matter for clarity's sake
    };
    
    int main() {
        Foo f;
        std::cout <<"b.i="<< deduce(f.getB())->i <<std::endl; // Prints 'b.i=5'
        return 0;
    }