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

Access protected members of an existing base object

假设我有一个基础 class 受保护的成员:

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

protected:
    int m_attribute;
};

并从基础派生 class:

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

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

如果是,那么问题是:

我是否应该先从这个基础 class 对象向下转换为派生 class 对象,然后再调用 get_attribute() 函数?像这样:

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

或者访问受保护成员的其他方式是什么?我知道 friend 函数是一个选项,但我无法更改 base class

中的任何内容

Derived class 可以访问和修改 publicprotected Base class 属性和方法。

那么,你不能将 Base 大小写成 Derived。 Derived继承自Base,所以Derived是一个Base。 但是 Base 不是 Derived(Car 是 Vehicle,Vehicle 不是 Car)。

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

首先:

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();

EDIT: static_cast 在运行时没有任何开销。它是 static,因此它是编译时的东西。两种方法都会产生相同的结果。

Should I do downcasting from this base class object to derived class object first, and then call get_attribute() function?

绝对不是。基础 class 的实例不是派生 class 的实例。您的转换格式错误。

这是一个有效的方法:

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

用法:

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

这种拼凑是通过复制构造派生类型的基础子对象来实现的。这当然取决于可复制的基础 - 你的 Base 是。也很容易调整以使用可移动的。

作为语法糖,组合可以隐式转换为成员的类型。如果您愿意,可以使用 getter.

如果基 class 在重载它以获取一些参数后没有默认构造函数并且没有默认构造函数那么派生的 classes 必须使用成员初始化列表来初始化base 部分否则你不能实例化派生的 class 让编译器抱怨 base class:

中缺少默认构造函数
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;

}
  • 您也不能将 class 基地址转换为派生对象,而是将 class 基地址转换为派生对象。

所以在你的例子中写在 main:

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

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