我昨天遇到了一个错误,虽然它很容易解决,但我想确保我正确理解C ++。
我有一个带有受保护成员的基类:
class Base
{
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
这编译并且工作得很好。现在我扩展Base但仍想使用b:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
请注意,在这种情况下,DoSomething
仍在引用Base
,而不是Derived
。我希望我仍然可以访问that.b
内的Derived
,但我收到cannot access protected member
错误(MSVC 8.0 - 还没有尝试过gcc)。
显然,在b
上添加公共getter解决了这个问题,但我想知道为什么我无法直接访问b
。我认为当你使用公共继承时,派生类仍然可以看到受保护的变量。
答案 0 :(得分:40)
您只能访问类型实例中的受保护成员(或从您的类型派生) 您无法访问父级或堂兄类型实例的受保护成员。
在您的情况下,Derived
类只能访问b
实例的Derived
成员,而不能访问其他Base
实例。
更改构造函数以获取Derived
实例也将解决问题。
答案 1 :(得分:4)
如上所述,这就是语言的运作方式。
另一个解决方案是利用继承并传递给父方法:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
Base::DoSomething(that);
d=0;
}
};
答案 2 :(得分:3)
您可以访问Derived
的受保护成员,但不能访问Base
的成员(即使它是Derived
受保护成员的唯一原因是因为它继承自Base
}})
答案 3 :(得分:3)
protected
个成员:
this
指针要解决您的情况,您可以使用最后两个选项之一。
在Derived :: DoSomething中接受派生或将派生friend
声明为Base:
class Derived;
class Base
{
friend class Derived;
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
在某些情况下,您也可以考虑使用公共吸气剂。
答案 4 :(得分:1)
class Derived : public Base
{
protected:
int d;
public:
void DoSomething()
{
b+=this->b;
d=0;
}
};
//this will work
答案 5 :(得分:1)
在hack for stl之后,我写了一个小代码,似乎解决了在派生类中访问受保护成员的问题
#include <iostream>
class B
{
protected:
int a;
public:
void dosmth()
{
a = 4;
}
void print() {std::cout<<"a="<<a<<std::endl;}
};
class D: private B
{
public:
void dosmth(B &b)
{
b.*&D::a = 5;
}
};
int main(int argc, const char * argv[]) {
B b;
D d;
b.dosmth();
b.print();
d.dosmth(b);
b.print();
return 0;
}
打印
a=4
a=5
答案 6 :(得分:0)
您可以尝试使用 static_cast
class Base
{
protected:
int b;
public:
...
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b += static_cast<const Derived*>(&that)->Base::b;
d=0;
}
void DoSomething(const Base* that)
{
b += static_cast<const Derived*>(that)->Base::b;
d=0;
}
};