访问现有基础对象的受保护成员

时间:2016-10-30 22:34:42

标签: c++ casting protected

假设我有一个带有受保护成员的基类:

class Base  
{
public:
    Base(int data)
    : m_attribute(data) {}

protected:
    int m_attribute;
};

来自base的派生类:

class Derived : public Base 
{
 public:
    int get_attribute()
    {
        return m_attribute;
    }   
};

首先:我可以做到这一点,对吧?这完全合法吗?

如果是,那么这就是问题:

  • 我无法改变基类中的任何内容;
  • 我有一个Base类对象,我需要访问它的m_attribute成员;

我应该首先从这个基类对象向下转换为派生类对象,然后调用get_attribute()函数吗?像这样:

Base base(5);
Derived* derived = static_cast < Derived*>(&base);
int base_attribute = derived->get_attribute();

或者访问受保护成员的其他方式有哪些?我知道朋友功能是一个选项,但我无法改变基类中的任何内容

4 个答案:

答案 0 :(得分:3)

  

我应该首先从这个基类对象向下转换为派生类对象,然后调用get_attribute()函数吗?

绝对不是。基类的实例不是派生类的实例。你的转换是不正确的。

这是一种有效的方式:

struct kludge : Base {
    kludge(const Base& b): Base(b) {}
    operator int() {
        return m_attribute;
    }
};

用法:

Base base(5);
int foo = kludge(base);

此kludge通过复制构建派生类型的基础子对象来工作。这当然取决于可复制的基础 - 您的Base是哪个。调整也很容易使用移动设备。

作为一种语法糖,kludge可以隐式转换为成员的类型。如果您愿意,可以使用吸气剂。

答案 1 :(得分:0)

如果基类在重载它之后没有默认构造函数来获取一些参数并且没有默认值,则派生类必须使用member-initializer list来初始化基本部分,否则你无法实例化派生类获取编译器抱怨缺少基类中的默认构造函数:

class Base  
{
    public:
    //  Base(){} default constructor by default the compiler creates one for you unless you overload it so the next one taking one parameter will hide this one
        Base(int data) // hides the default ctor so derived classes must use member-initializer list
        : m_attribute(data) {}

    protected:
        int m_attribute;
};


class Derived : public Base 
{
    public:
        Derived() : Base(0){} // you must use member intializer list to initialize the part Base
        //Derived(int x) : Base(x){} // also ok
        int get_attribute(){ return m_attribute; }   
};

int main()
{
    Derived dervObj;

    Derived* derived = static_cast < Derived*>(&baseObj);
    int base_attribute = derived->get_attribute();
    cout << base_attribute << endl;

}
  • 你也不能将类库的地址强制转换为派生对象,而是将基类的对象强制转换为派生对象。

所以在你的例子写在main:

Derived* derived = static_cast < Derived*>(&baseObj); // is like writing:
char* cp = static_cast < char*>(&int); // you must convert a variable not a type
  • 为什么要从外部访问受保护的成员?请记住,公共继承会将base的所有成员复制到派生类,但私有。

  • 使用友谊或公开成员数据可以从外部访问它,但它破坏了数据隐藏和封装的原则,但友情在某些情况下是必须的,没有其他选择,然后小心使用它但要公开数据,最好回到结构

答案 2 :(得分:-1)

Derived类可以访问和修改publicprotected基类属性和方法。

然后,你不能将Base编入Derived。 派生继承自Base,因此Derived是Base。 但是基地不是衍生的(汽车是车辆,车辆不是汽车)。

因此,如果您需要一个getter,请将其直接放入Base,或者实现Derived而不是Base。

答案 3 :(得分:-1)

首先:

<div id="div1">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iure mollitia molestias recusandae nulla placeat repellat odio eos. Blanditiis nulla suscipit sequi ducimus distinctio quo tempore.</p>
</div>
<div id="div2">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iure mollitia molestias recusandae nulla placeat repellat odio eos. Blanditiis nulla suscipit sequi ducimus distinctio quo tempore.</p>
</div>
<div id="div3">
</div>
<div id="div4">
</div>
<div id="div5">
</div>
<div id="div6">
</div>

这是无效和非法的。不会编译。您无法将Derived* derived = static_cast < Base*>(base); 静态转换为Base

回答你的问题:

Base*

或者如果你想使用指针,因为你认为你更酷:

Base base(5);
Derived& derived = static_cast<Derived&>(base);
std::cout << derived.get_attribute();

编辑Base base(5); Derived* derived = static_cast<Derived*>(&base); std::cout << derived->get_attribute(); 在运行时没有任何开销。它是 static ,因此它是编译时的东西。两种方法都会产生相同的结果。