Subtle C++ Inheritance Error with Protected Fields

Multiple inheritance compilation error with inheriting protected functions and public variables C++

You don't define the function showRoomServiceMeal as a part of the RoomServiceMeal class:

void showRoomServiceMeal()
{
...
}

Change to

void RoomServiceMeal::showRoomServiceMeal()
{
...
}

Also, in the showRoomServiceMeal method you don't have to use the class prefix when accessing the parent classes members. Instead of using e.g. RestaurantMeal::price you can just use price. This is because the variables and functions are unique in each class.

trouble with inheritance: derived class not inheriting base class

The initialization list of a constructor isn't able to initialize any members of a parent class. Instead, you should call the parent constructor that will do the proper initialization.

    SortedSet::SortedSet(const SortedSet &s) : IntList(s) // ...

Confusion regarding protected member functions and derived class access

If the compiler allows such thing, then you can easily break encapsulation. Think about this:

base b;
a foo;
foo.fa(b); // we can now easily access/modify protected elements of `b`

In this case, there is no relation between the derived object foo and the base b, however you can use a derived to access its "guts". This should not be possible (at least imho).

Just doing f() inside a.fa() is OK, since you just modify the base part of a, and not some un-related object.

To be more specific, you can write a "wrapper" which will disable protected for any class:

#include <iostream>

class Base
{
public: // protected in your case, public here so it compiles
int x{42};
public:
int getx() {return x;}
};

template<typename T> // wrapper
class DisableProtected: public T
{
public:
void modify(Base* b)
{
b->x = 24;
}
};

int main()
{
Base base;
std::cout << base.getx() << std::endl;
DisableProtected<Base> foo;

foo.modify(&base); // can modify any Base
std::cout << base.getx() << std::endl;
}

A little rusty on C++ class inheritance

The problem is Datum::Datum *right is protected. Pointer right is accessible / assignable because the base class is inherited publicly. But the object pointed by right has no access previliges the way you are trying to in the member function Column::cover() because the object pointed by right has no direct relation in the current scope of the derived class.

 void cover() {
// Not posssible right->left = left;

// But -
right = new Datum(); // Assuming the class has default constructor.
}

Similar is the problem for the Datum::Datum *left too.

Can a member function (as opposed to the entire class) befriend a function/class?

There is no way to do this directly with friendship, but you can achieve a similar effect with a modification of tag-based dispatching:

class C
{
public:
class AccessTag
{
friend class C;
friend void F();
private:
AccessTag() {}
};

void functionToAccess(AccessTag)
{
std::cout << "Restricted function called!\n";
}
};

void F()
{
C c;
c.functionToAccess(C::AccessTag()); // OK
}

void nonF()
{
C c;
c.functionToAccess(C::AccessTag()); // error, nonF cannot access ctor of C::AccesTag
}

The idea is to only allow functionToAccess to be called by those who can construct a C::AccessTag object. And because of its private constructor, C::AccessTag can only be constructed by its friends. These are C (so that it can call functionToAccess itself, as it could any other of its private functions), and F. F cannot access any other non-public members of C, because it is not a friend of C.

You can even have different access tags for different member functions (or groups of member functions).

Why can't I call the base class operator from derived class?

Instead of trying to do the static casts yourself to try and get the compiler to resolve to call the Base operator, you can just explicitly call the Base comparison operator.

In addition, since this won't be modifying the object, you should probably make this method (and the base method) const.

Altogether that'd look like:

bool operator == ( const Derived& other ) const
{
return Base::operator==(other);
}

See it run here: ideone

C++ Polymorphism does not work as expected

The problem

In your base class you define the pure virtual member function:

virtual void foo(Base&, const int&, const int&) const = 0;

but you provide in the derived a function with another signature:

void foo(Derived&, const int&, const int&) const;

So you have one more member function in the derived class (an overload: same name but different parameter types), but still the inherit the pure virtual function. So the derived class is as abstract as the base class and you're not allowed to instantiate it.

The solution

In the derived class change the signature so that it matches the pure virtual bas e member function:

void foo(Base&, const int&, const int&) const;

By the way, whenever you use virtual functions, use override keyword to spot these kind of subtle errors at compilation, even for ordinary virtual functions:

void foo(Base&, const int&, const int&) const override;

More infos

Indeed, once you define your foo() with a Base parameter, you can't use easily the iD member.

The first solution is to use a dynamic_cast to tell your code that the base is in fact a derived object. Of course you have to check if this assumption is correct:

void Derived::foo(Base& d, const int& i1, const int& i2) const{ 
Derived *dp = dynamic_cast<Derived*>(&d);
if (dp) {
std::cout << dp->iD;
}
}

However, what is not clear to me is why you need this first in a first place. Why not get rid of this first type dependent parameter and use the member variables of the current object:

void Derived::foo(const int& i1, const int& i2) const{ 
std::cout << iD;
}


Related Topics



Leave a reply



Submit