访问派生类中的受保护成员 昨天我遇到了一个错误,虽然很容易绕过,但我想确保我理解C++正确。
我有一个具有受保护成员的基类:访问派生类中的受保护成员 昨天我遇到了一个错误,虽然很容易绕过,但我想确保我理解C++正确。,c++,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 DoSome
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
仍然引用基
,而不是派生
。我希望我仍然可以访问派生的中的that.b
,但我得到了一个无法访问受保护成员的错误(MSVC 8.0-尚未尝试gcc)
显然,在b
上添加公共getter解决了这个问题,但我想知道为什么我不能直接访问b
。我认为当使用公共继承时,受保护的变量对派生类仍然可见。类只能访问此类或派生类实例的受保护成员。它无法访问父类或表亲类实例的受保护成员
在您的情况下,Derived
类只能访问Derived
实例的b
受保护成员,而不能访问Base
实例的受保护成员
将构造函数更改为获取派生的
实例将解决此问题。您可以访问派生的
的受保护成员,但不能访问基的受保护成员(即使它是派生的
受保护成员的唯一原因是因为它是从基继承的)如前所述,这就是语言的工作方式
另一种解决方案是利用继承并传递给父方法:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
Base::DoSomething(that);
d=0;
}
};
使用此
指针访问受保护的成员
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
this->b+=that.b;
d=0;
}
};
受保护的
成员可以访问:
- 通过
此
指针
- 或相同类型的受保护成员(即使在基中声明)
- 或者来自朋友类、函数
要解决您的问题,您可以使用最后两个选项之一
接受派生::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;
}
};
你也可以考虑一些公共吸气剂。< /P> < P>你可以尝试使用<强> STATICOSTCAST < const派生>(pBASE)-> Base::
class Derived : public Base
{
protected:
int d;
public:
void DoSomething()
{
b+=this->b;
d=0;
}
};
//this will work
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;
}
};
类基
{
受保护的:
int b;
公众:
...
};
派生类:公共基
{
受保护的:
int d;
公众:
无效剂量测量(常数基和该)
{
b+=静态_cast(&that)->Base::b;
d=0;
}
无效剂量测量(常数基*该值)
{
b+=静态_cast(that)->Base::b;
d=0;
}
};
接下来,我编写了一个小代码,似乎可以解决访问派生类中受保护成员的问题
#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;
}
在这个问题上,我举了一个糟糕的例子,但我不能称之为Base::DoSomething,因为DoSomething实际上在它进入派生类而不是基类时做的事情是不同的。请检查(注意:不要在生产代码中使用这些东西)。@AnishaKaul:您只能在您类型的实例中访问基类的受保护成员,不是表亲类型。例如,按钮
无法从文本框
上的控件
访问受保护的属性
您只能在类型的实例中访问基类的受保护成员,而不能访问表亲类型
您再次编写了与上面编写的相同的语句。请看这里:@SLaks“将构造函数更改为获取派生实例也可以解决问题”是什么意思?@SLaks但为什么基类的实例可以访问该基类的其他实例的pivate成员?基类中的访问器方法如何,虚拟和受保护,您可以从派生类调用,并传递对基类或派生类的另一个实例的引用?这不起作用。考虑“您可以访问<代码>私下<代码>成员<代码>派生<代码>”和“继承的<代码>私下< /代码> <代码> Base<代码>的成员。这个答案是错误的。派生类无法访问基类的“b”,因为它被声明为受保护(这是用户首先要求的)。此代码将生成一个编译器错误。这是一个多么不正确的答案。问题在于的b
。添加这个->
不仅是不相关的,而且是完全不可操作的,因为如果省略它,它是隐含的。我希望人们能对一种语言略知一二,并在将其作为答案发布之前测试他们编写的任何代码。这是有效的(至少在visual studio 2019中),我不知道为什么会被否决。如果的动态类型不是(cv)派生的,但在这种情况下,b始终是基类的数据成员!或者更好,您可以使用:b+=static_cast(that)->Base::b;事实证明,我的示例与上面发布的示例几乎相同。我还想知道它是否有效。从我的观点来看,这可能会导致转换为派生类型,但我不确定。
a=4
a=5