Call the protected base class method using this pointer assigned to the base class in the derived class (C ++)

To begin with, what I know about the C ++ standard (ISO / IEC 14882: 2003): section 11.5, paragraph 1, and this is not the case (but it seems that the compiler does not think so).

I try to call the protected base class method in the derived class method using this pointer, statically-casted to the base class pointer and in MSVC2008 error C2248: "A :: f": cannot access the protected member declared in class "A" .

I need to do this in the context of a “curiously repeating template pattern”, but I can reproduce this error in simpler code, as shown below:

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

, , ?

, ?


, :

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


, , , class E : public B<D> {...};: , static_cast .

+5
3

. - B::f, :

this->B::f();

:

11.4 [class.protected]

[...] , - C. [...] [...] [s] a ( ) (5.2.5). , C , C.

, B . , this->B::f(), .


CRTP , f() static_cast, D B<D> ( ). D B<D>, protected B<D> . - friend B<D> - D static_cast this:

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 CRTP- D:

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, .

+13

, .

:

void g()
{
    B *b1 = this;
    B *b2 = GetUnrelatedB();
    b1->f(); //Error?
    b2->f(); //Error!
}

b1 static_cast, , b1 , b2 .

11.5:

[...] , .

static_cast<B*>(this) B*, D*, , . , , :

void g()
{
    B *b2 = GetUnrelatedB();
    static_cast<D*>(b2)->f(); //ok!
}
+1

But how does the compiler know that you are inside a class derived from B after applying static_castto this? In my (humble) opinion, if I create an object B, I expect that it will not be allowed to call private or protected methods of the Bobject B, since we do not want to break encapsulation. It does not matter where the object is created Bif it is outside the class methods B.

0
source

All Articles