我一直在努力思考从C++中的一些测试代码访问受保护成员函数的最佳方法,这是我的问题:
//in Foo.h
Class Foo
{
protected:
void DoSomething(Data data);
}
//in Blah.h
Class Blah
{
public:
Foo foo;
Data data;
};
//in test code...
Blah blah;
blah.foo.DoSomething(blah.data); // Here's my problem!
Run Code Online (Sandbox Code Playgroud)
到目前为止一些可能的解
欢迎所有建议/见解/意见!
谢谢
我写了以下代码:
public class A
{
protected string Howdy = "Howdy!";
}
public class B : A
{
public void CallHowdy()
{
A a = new A();
Console.WriteLine(a.Howdy);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在VS2010其中导致以下编译错误:
无法通过"A"类型的限定符访问受保护的成员"Aa"; 限定符必须是'B'类型(或从中派生).
这对我来说似乎很不合逻辑 - 为什么我不能protected从类的方法访问类实例的字段,这是从它派生的?
那么,为什么会这样呢?
找到了严格的答案 - http://blogs.msdn.com/b/ericlippert/archive/2005/11/09/491031.aspx
我想bind()从派生类到我的基类的函数版本.该功能在基础中标记为受保护.当我这样做时,代码在Clang(Apple LLVM编译器4.1)中快速编译,但在g ++ 4.7.2和Visual Studio 2010中都出错.错误是:"'Base :: foo':不能访问受保护的成员."
这意味着参考的上下文实际上在bind()其中,当然这个函数被视为受保护.但是不应该bind()继承调用函数的上下文 - 在这种情况下,Derived::foo()- 因此将基本方法看作是可访问的?
以下程序说明了该问题.
struct Base
{
protected: virtual void foo() {}
};
struct Derived : public Base
{
protected:
virtual void foo() override
{
Base::foo(); // Legal
auto fn = std::bind( &Derived::foo,
std::placeholders::_1 ); // Legal but unwanted.
fn( this );
auto fn2 = std::bind( &Base::foo,
std::placeholders::_1 ); // ILLEGAL in G++ 4.7.2 and VS2010.
fn2( this );
}
};
Run Code Online (Sandbox Code Playgroud)
为什么行为上的差异?哪个是对的?错误提供编译器有哪些可用的解决方法?
我们有这种情况,并想知道解决它的最佳方法
template<typename T>
struct A : T {
A(T &&t) noexcept(noexcept(T(std::move(t))))
:T(std::move(t))
{ }
};
Run Code Online (Sandbox Code Playgroud)
遗憾的是,这无法编译,因为T的移动构造函数受到保护,我们只允许在构造函数初始化列表中调用它*this.有什么办法使这项工作或甚至有一个标准的方法呢?
/*Child is inherited from Parent*/
class Parent {
public:
Parent () //Constructor
{
cout << "\n Parent constructor called\n" << endl;
}
protected:
~Parent() //Dtor
{
cout << "\n Parent destructor called\n" << endl;
}
};
class Child : public Parent
{
public:
Child () //Ctor
{
cout << "\nChild constructor called\n" << endl;
}
~Child() //dtor
{
cout << "\nChild destructor called\n" << endl;
}
};
int main ()
{
Parent * p2 = new Child;
delete p2;
return …Run Code Online (Sandbox Code Playgroud) 我找到了静态类包含未声明为静态的方法的代码.编译器不显示任何警告.这看起来很混乱,不是吗?
我在理解java中的受保护访问修饰符(或其背后的设计)时遇到了一些麻烦.我认为这意味着包访问和访问通过继承包含抽象成员的类的对象.
我写了以下示例代码.我看到如果取消注释,注释掉的行会产生编译错误.为什么我可以通过Second中的Second对象访问pro,但不能通过Second中的First对象访问pro?
package first;
public class First {
protected void pro(){
System.out.println("Can see protected method");
}
}
Run Code Online (Sandbox Code Playgroud)
package first;
public class InFirst {
public static void main(String[] args){
First fst = new First();
fst.pro();
}
}
Run Code Online (Sandbox Code Playgroud)
package second;
import first.First;
public class Second extends First {
public static void main(String[] args){
First fst = new First();
// fst.pro();
Second sec = new Second();
sec.pro();
}
}
Run Code Online (Sandbox Code Playgroud) 从[class.access]/7我们得到以下句子:
类似地,
A::B作为基本说明符的使用是良好形成的,因为它D是派生自的A,因此必须推迟对基本说明符 s的检查,直到看到整个基本说明符列表.
class A {
protected:
struct B { };
};
struct D: A::B, A { };
Run Code Online (Sandbox Code Playgroud)
查看clang的实例.事实上,clang还抱怨这个片段,不需要延期.
class A {
protected:
struct B { };
};
struct D: A, A::B { };
Run Code Online (Sandbox Code Playgroud)
为什么这段代码不能编译?
PS:gcc和VS21013也不编译代码.
任何人都可以向我解释为什么(例如,"为什么语言是这样的?")以下代码在第二行有编译错误B::C::bar?
class A
{
public:
struct D
{
void call_foo (A &a)
{
a.foo ();
}
};
protected:
void foo () {}
};
class B : public A
{
struct C : public A::D
{
void bar (A &a, B &b)
{
b.foo (); // OK
a.foo (); // Error. Huh?
call_foo (a); // Ugly workaround
}
};
};
Run Code Online (Sandbox Code Playgroud)
当且仅当基指针的类型恰好是封闭类型(而不是某些父类型)时,似乎方法可以安全地在父类中使用受保护的方法.
这看起来很奇怪.为什么这种语言呢?
请考虑以下示例
class base
{
protected :
int x = 5;
int(base::*g);
};
class derived :public base
{
void declare_value();
derived();
};
void derived:: declare_value()
{
g = &base::x;
}
derived::derived()
:base()
{}
Run Code Online (Sandbox Code Playgroud)
根据知识,只有基类的朋友和派生类可以访问基类的受保护成员,但在上面的示例中,我得到以下错误,"Error C2248 'base::x': cannot access protected member declared in class "但是当我添加以下行时
friend class derived;
Run Code Online (Sandbox Code Playgroud)
声明它是朋友,我可以访问基类的成员,我在声明派生类时做了一些基本的错误吗?