Sam*_*Lou 17 c++ language-lawyer c++11
我做了这个简单的课程,仍然在玩我的想法:
class A {
private:
class B {};
public:
B getB() {
return B();
};
};
Run Code Online (Sandbox Code Playgroud)
从C++ 03开始,这个类编译得很好,但是没有很好的方法可以将结果分配给getB()左值,在这个意义上:
A::B b = A().getB();
Run Code Online (Sandbox Code Playgroud)
不编译.
我通过使用中间模板得到它,以这种方式:
template <typename T>
struct HideType {
typedef T type;
};
HideType<A::B>::type b = A().getB();
Run Code Online (Sandbox Code Playgroud)
但这看起来很糟糕,因为这个简单的任务是得到一个A :: B左值变量.
从C++ 11开始就不再这样了,或者至少它不适用于gcc.此代码仍无效:
A::B b = A().getB();
Run Code Online (Sandbox Code Playgroud)
但这是有效的:
auto b = A().getB();
Run Code Online (Sandbox Code Playgroud)
标准方面是否存在漏洞?
Vic*_*nko 10
从标准,第11条(会员访问控制):
班级成员可以是
私人的; 也就是说,它的名称只能由声明它的类的成员和朋友使用.
- 受保护; 也就是说,它的名称只能由声明它的类的成员和朋友,从该类派生的类以及他们的朋友使用(见11.4).
- 上市; 也就是说,它的名称可以在没有访问限制的任何地方使用.
因此,访问控制应用于名称.
在
auto b = A().getB();
Run Code Online (Sandbox Code Playgroud)
根据标准,你不使用私人名称,因此它是合法的
A::B b = A().getB()之所以不起作用的事实是因为B是 的私有类成员A。如果您将其公开,那么您的代码将被编译。它可以工作auto,因为auto只需检查分配给它的对象的类型,而不需要调用对象的构造函数(就像declval)。因此它分配了class 中presentb的返回类型。您也可以通过以下方式更改代码:getBA
decltype( declval<A>().getB() ) b = A().getB();
Run Code Online (Sandbox Code Playgroud)
(如果declval对您来说是新的,那么我必须告诉您,它将返回类(此处)的函数(此处getB其返回类型是B)的返回类型的右值A,而不调用该类的构造函数!(但这应该是与decltypeand sizeofonly 等函数一起使用。)因此它可以防止创建类对象然后使用其函数的开销。)
现在根据我的说法,我不认为这是标准中的漏洞,而是我觉得漏洞已经被删除了!从您自己的代码中可以明显看出,请参阅该函数getB。实例化一个对象是多么困难,B因为它是在 private 中定义的!在这种情况下,合作B变得很困难。B这背后的想法是,类中的类型名称(即)A无法访问,但该类型仍然可用,这就是为什么您可以获得 的对象B。auto如果你理解这个模板代码,你就可以理解它的用法:-
#include <iostream>
#include <type_traits> // for std::is_same
using namespace std;
class A
{
class B
{};
public:
B getB()
{
return B();
}
};
template<typename T>
void check (T b)
{
cout<<boolalpha;
is_same<decltype( declval<A>().getB() ), T> x; // checks if T & B are of same type
cout<<x.value<<'\n';
}
int main()
{
A obj;
check (obj.getB());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出 :-
true
Run Code Online (Sandbox Code Playgroud)
由于template可以识别B,因此auto也可以识别B。