c++ - 通过此指针调用 protected 基类方法并转换为派生类中的基类 (C++)

标签 c++ inheritance compiler-errors protected

首先,我了解 C++ 标准 (ISO/IEC 14882:2003):第 11.5 节第 1 段,但事实并非如此(但编译器显然不这么认为)。

我尝试通过 this 指针在派生类方法中调用 protected 基类方法,静态转换为基类指针并在 MSVC2008 错误 C2248: 'A::f' 中:无法访问类“A”中声明的 protected 成员

必须在“奇怪的重复模板模式”的上下文中执行此操作,但我可以用更简单的代码重现此错误,如下所示:

class B
{
protected:
    void f(){}
};

class D : public B
{
public:
    void g()
    {
        f(); // ok
        this->f(); // ok
        static_cast<B*>(this)->f(); // C2248 in MSVC2008
        dynamic_cast<B*>(this)->f(); // C2248
        ((B*)this)->f(); // C2248
    }
};
D d; d.g();

编译器似乎将强制转换的 this 指针视为指向其他实例的指针,是吗?

编译器在这种情况下是错误的,你怎么看?


好吧,我的真实代码更像这样:

template<class T>
class B
{
public:
    void g()
    {
        f(); // error C3861: 'f': identifier not found
        this->f(); // error C3861: 'f': identifier not found

        // static_cast to derived class
        static_cast<T*>(this)->f(); // C2248 in MSVC2008
    }
};

class D : public B<D>
{
protected:
    void f(){}
};

我将 this 转换为 derived 类,但我不能使用 this->f();


顺便说一句,我看到这段代码对于像 class E : public B<D> {...}; 这样的用法是不安全的: 可编译,但 static_cast 进行了错误的转换。

最佳答案

编译器是正确的。显式访问 B::f成员函数,可以这样写:

this->B::f();

相关语言是:

11.4 Protected member access [class.protected]

[...] Access to a protected member is granted because the reference occurs in a friend or member of some class C. [...] Access to a protected member [...] involve[s] a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C.

因此通过转换为基类来保护成员访问 B违反了这项授权,并且是不允许的。这也是不必要的,因为您可以使用 this->B::f()如上。


在您实际的 CRTP 动机的情况下,您不能调用 f() 是正确的没有 static_cast , 自 D不是 B<D> 的基类(继承关系是反方向的)。自 D不是 B<D> 的基类, 你不能调用它的 protected来自 B<D> 的方法反正。一种简单的解决方法是 friend B<D>D并使用 static_castthis 上指针:

template<typename T>
class B {
public:
    void g() {
        static_cast<T *>(this)->f();
    }
};

class D : public B<D>
{
    friend class B<D>;
    ...

如果给B访问 private部分 D担心你,你可以移动private部分到另一个基类并隔离 D 中的 CRTP 机制:

template<class T> class B {
public:
    void g() {
        static_cast<T*>(this)->f();
    }
};

class C {
private:
    void h();
protected:
    void f(){ std::cout << "D::f\n"; }
};

class D: protected C, public B<D>
{
    friend class B<D>;
};

在这里B<D>无法调用 C::h因为友元既不能继承也不能传递。

关于c++ - 通过此指针调用 protected 基类方法并转换为派生类中的基类 (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11795349/

相关文章:

compiler-errors - 生成/ fork : Cannot allocate memory中的Crystal未处理的异常

java "Cannot resolve method ' setCharAt(int, 字符 )'"

c++ - 用.txt文件编译多个C++文件?

c++ - 用C++获取网站缩略图快照

c++ - 如何使用 Visual Studio 自动记录断言?

c++ - __declspec() 中的 "storage-class information"是什么意思?

c++ - ifstream readsome 究竟是如何工作的

c# - 接口(interface)继承与类继承相结合

c++ - 在构造函数继承中使用默认构造函数

java - 依赖父类(super class)抛出异常