Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 转发类声明是否可以在使用位置与class关键字互换?_C++ - Fatal编程技术网

C++ 转发类声明是否可以在使用位置与class关键字互换?

C++ 转发类声明是否可以在使用位置与class关键字互换?,c++,C++,这两个相等吗 代码1: class B; class A { public: B fun1() const; B* m_b; }; extern void myfun( const B& b ); 代码2: class A { public: class B fun1() const; class B* m_b; }; extern void myfun( const class B& b ); 或者代码2中的使用编程风格是否存在一些问题

这两个相等吗

代码1:

class B;

class A {
public:
    B fun1() const;
    B* m_b;
};

extern void myfun( const B& b );
代码2:

class A {
public:
    class B fun1() const;
    class B* m_b;
};

extern void myfun( const class B& b );

或者代码2中的使用编程风格是否存在一些问题?

如果您有一个封闭的范围,这些问题就不同了

案例1:

class B { };
namespace test {
    class B;  // declares test::B

    class A {
    public:
        B fun1() const; // refers to test::B
        B* m_b;         // also refers to test::B
    };

    class B { int x; };  // defines test::B
}
案例2:

class B { };
namespace test {
    class A {
    public:
        class B fun1() const; // refers to ::B
        class B* m_b;         // also refers to ::B
    };

    class B { int x; };  // defines test::B
}

更多详情:

B类是两件事之一。它要么是重新声明,要么是将名称
B
引入当前范围的转发声明(§9.1[类名称]/p2)

类B
本身被称为一个精心设计的类型说明符。当您使用它声明某些内容时,编译器首先查找名为
B
的类型是否在范围内(§3.4.4[basic.lookup.elab]/p2,§9.1[class.name]/p3注释)。如果有,则使用详细的类型说明符来引用该说明符

如果没有,那么它还将声明一个新名称。转发声明的区别在于声明此新名称的范围。如果用于指定命名空间作用域函数的返回类型或参数类型,则需要在包含声明的命名空间中声明名称;否则,除了作为友元声明外,该名称将在包含该声明的最小命名空间或块作用域中声明(§3.3.2[basic.scope.pdecl]/p7)。注意,这永远不会在类范围中声明名称;换句话说,它永远不会声明嵌套类

为什么使用前向声明而不是替代声明?首先,它可以在任何范围内声明名称,而不仅仅是块和命名空间范围。其次,前瞻性声明不那么脆弱。注意,在第二种情况下,如果我将
test::B
的定义移动到
test::A
之前,那么
test::A
中的
class B
s突然指代
test::B
,而不是
::B
。第三,您真的想记住一整段关于声明名称放入哪个范围的规则吗