这是标准的 C++ 吗?代码?
下面这段简单的代码,用 VC2008 编译,但 g++ 拒绝了该代码:
#include <iostream>
class myclass
{
protected:
void print() { std::cout << "myclass::print();"; }
};
struct access : private myclass
{
static void access_print(myclass& object)
{
// g++ and Comeau reject this line but not VC++
void (myclass::*function) () = &myclass::print;
(object.*function)();
}
};
int main()
{
myclass object;
access::access_print(object);
}
(/W4)
在 VC 中打开,但没有给出任何警告。
g++ 4.4.1 给我一个错误:
correct.cpp: In static member function ‘static void access::access_print(myclass&)’:
correct.cpp:6: error: ‘void myclass::print()’ is protected
如果 g++ 是正确的,我如何访问类的受保护成员?还有别的办法吗?
@Suroot你的意思是我不应该传递myclass
类型的对象吗?实际上没关系,g++ 给出了相同的错误,但 VC 编译代码时没有任何警告。
#include <iostream>
class myclass
{
protected:
void print() { std::cout << "myclass::print();"; }
};
struct access : private myclass
{
static void access_print()
{
myclass object;
void (myclass::*function) () = &myclass::print;
(object.*function)();
}
};
int main()
{
access::access_print();
}
The following simple piece of code, compiles with VC2008 but g++ rejects the code:
#include <iostream>
class myclass
{
protected:
void print() { std::cout << "myclass::print();"; }
};
struct access : private myclass
{
static void access_print(myclass& object)
{
// g++ and Comeau reject this line but not VC++
void (myclass::*function) () = &myclass::print;
(object.*function)();
}
};
int main()
{
myclass object;
access::access_print(object);
}
(/W4)
is turned on in VC, but it doesn't give any warning.
g++ 4.4.1 gives me an error:
correct.cpp: In static member function ‘static void access::access_print(myclass&)’:
correct.cpp:6: error: ‘void myclass::print()’ is protected
If g++ is correct, how do I access a protected member of a class? is there another way?
@Suroot Do you mean that I shouldn't pass an object of type myclass
? It doesn't matter actually, g++ gives the same error but VC compiles the code without any warning.
#include <iostream>
class myclass
{
protected:
void print() { std::cout << "myclass::print();"; }
};
struct access : private myclass
{
static void access_print()
{
myclass object;
void (myclass::*function) () = &myclass::print;
(object.*function)();
}
};
int main()
{
access::access_print();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是正确的。上面已经引用了该标准的相关部分,但这里是其价值的基本原理。
C++ 中
protected
的语义意味着“可以从此类或任何派生类的方法访问此成员,但只有当所访问的对象的动态类型保证与以下内容相同时,或派生自*this
”的类型。后一点可能不太明显,所以这里有一个例子:
这是设计使然 - 这个想法是
Derived2
可以对如何处理其受保护的成员有自己的看法(不变量是什么等),并且它应该严格位于它和它的基类(及其派生类,但前提是它决定不通过将其设为私有来隐藏该字段时)。跨层次结构访问与此模型相反,因为它实际上意味着基类提前决定整个层次结构;对于深层层次结构之上的非常抽象的类,这可能是不可取的。现在回到你的具体问题 - 现在应该相当明显了。一旦获得成员函数指针,就可以使用任何匹配类型的接收器调用该指针指向的函数。对于基类的受保护方法,这意味着,如果您可以获得指向基类(而不是您自己的类)类型的指针,则可以调用它,并将其传递给与您的类型不同的类型的指针类(或派生自该类),违反了上述受保护访问的规则。因此,您不允许这样做。
This is correct. The relevant part of the Standard has been quoted above, but here's the rationale for what it's worth.
The semantics of
protected
in C++ means "this member can be accessed from methods of this class or any derived classes, but only when dynamic type of object being accessed is guaranteed to be the same as, or derived from, the type of*this
".The latter bit may not quite be obvious, so here is an example:
This is by design - the idea is that
Derived2
could have its own opinion on how its protected members should be handled (what are the invariants, etc), and it should be strictly between it and its base class (and its derived classes, but only if it decides to not hide that field by making itprivate
). Cross-hierarchy access is contrary to this model, since it would effectively mean that the base class decides for the entire hierarchy in advance; for very abstract classes on top of deep hierarchies, this can be undesirable.Now back to your specific problem - it should be fairly obvious by now. Once you obtain a member function pointer, you may call the function pointed to by that pointer with any receiver of a matching type. For a protected method of a base class, this means that, if you could obtain a pointer to it typed to the base class (rather than your own class), you could then call it, passing it a pointer to a type different from your class (or derived from it), violating the rules for protected access outlined above. Therefore, you are not permitted to do this.
我相信 g++ 和 comeau 是正确的。受保护成员的说明符必须是“访问”类型或派生类型,因此我相信代码:
会编译。
我相信这是因为 11.5.1:
I believe g++ and comeau are correct. The specifier for a protected member must be of type "access" or derived, so I believe the code:
would compile.
I believe this is because of 11.5.1:
由于对象作为参数传递,因此您无法直接访问私有/受保护的函数。
编辑:
将 myclass 更改为对象
Since object is being passed as a parameter, you cannot access private/protected functions directly.
Edit:
Changed myclass to object