How to Cast a Derived Class to a Private Base Class, Using C-Style Cast

Can I cast a derived class to a private base class, using C-style cast?

Yes you can: §5.4/7 of the standard:

... the following static_cast and reinterpret_cast operations
(optionally followed by a const_cast operation) may be performed using
the cast notation of explicit type conversion, even if the base class
type is not accessible:

a pointer to an object of derived class type or an lvalue of derived
class type may be explicitly converted to a pointer or reference to an
unambiguous base class type, respectively;

But try not to as it defeats the purpose of private inheritance.

Why does C style cast allow you to convert to a private base class?

It's because in C it was allowed to convert any pointer to any other pointer using this cast and C++ tries to be C-compatible as much as possible, but tries to do a good job to be correct when it comes to classes, so C style cast is stronger than reinterpret_cast in this situation.

how to implement casting to a private base class in C++

If defining a public casting operator does not work, you can try with a regular function:

class D: private B {
public:
B& asB() { return static_cast<B&>(*this); }
};
...
D d;
d.asB().methodInB();
...

Anyway, what is the point? If D derives privately from B, then you are not supposed to use a D as a B from the outside.

Why doesn't this code cast a base class into a derived class in c++?

Whenever you push an object of b into vector vec of Base Objects, you create another object from temp which is purely of type base. You might be thinking (and you are not right!) that element which is being stored in vector will be of type Base but it will be holding an object of type bbut it's not how you achieve Dynamic Polymorphism in C++.

The statements:

std::vector<Base> vec; // 1
b temp; // 2
vec.push_back(temp); // 3

The third line will create a different object to type Base by calling assignment operator of base class Base operator=(const Base& ).

Also,b* temp = (b*)&vec[i]; is an undefined behavior because you are explicitly trying to cast a pointer to object of base to it's derived class type b but it doesn't hold object of type b and hence, you may get unexpected behavior.

NOTE:

Use dynamic_cast for casting between base and derived class as it will make sure that the conversion is valid. Otherwise, it will return nullptr. However, you need to make your base class polymorphic by having at least 1 virtual function.

If the cast is successful, dynamic_cast returns a value of type new-type. If the cast fails and new-type is a pointer type, it returns a null pointer of that type. If the cast fails and new-type is a reference type, it throws an exception that matches a handler of type std::bad_cast.

SOLUTION:

Use vector of pointers to base class to achieve run-time polymorphism.

std::vector<base *> vec;
for (int i = 0; i < 5; i++) {
b *temp = new b();
vec.push_back(temp);
}

for (int i = 0; i < 5; i++) {
b* temp = dynamic_cast<b *>(vec[i]); // For dynamic cast, you need to add virtual functions to your base class
if (temp != nullptr)
std::cout << temp->d << std::endl;
}

EDIT:

Object Slicing is also a solution for your problem. Object Slicing is the right keyword for this type of problems. Here is the definition of the Object Slicing

Object slicing happens when a derived class object is assigned to a base class object, additional attributes of a derived class object are sliced off to form the base class object.

I am quoting one of the answer in the link below. See this answer and answer for the best explanation and possible solution with some code snippet. See this article, it has explained the problem when pushing object of Derived class in a vector of base class.

"Slicing" is where you assign an object of a derived class to an instance of a base class, thereby losing part of the information - some of it is "sliced" away.

For example,

class A {
int foo;
};

class B : public A {
int bar;
};

So an object of type B has two data members, foo and bar.

Then if you were to write this:

B b;
A a = b;

Then the information in b about member bar is lost in a.

Why does explicit typecasting allow upcasting for private inheritance?

The cast in

A* a1 = (A*)new B;

is a cast to inaccessible base class.

It can only be expressed as a C style cast. It is equivalent to what a static_cast would do if a static_cast could be used in this situation, and it is not equivalent to a reinterpret_cast. In particular the result address is not necessarily the same as the argument address.

C++11 §5.4/4:

The same semantic restrictions and behaviors [as for a static_cast] apply [for a C style cast], with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible:

— a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;

Is it safe to cast a class to a derived class that just adds additional functions?

No, this isn't safe. The behaviour of the program is undefined.

Static casting to a derived type is safe only when the dynamic type of the object is that derived type (or a further derived type).

Difference among three explicit upcasting to a private base class

test subclasses string privately, so test "knows" it is a string, but anyone outside doesn't.

In your first case, what happens is as follows:

  1. Outside of test (in main), you call the show method. That's OK, because it's public.

  2. Now, inside show, the code "knows" it's of type string, because it's a method of test. The conversion is OK.

In your third case, though, you're trying to do the conversion outside, from main. Outside of test, main "doesn't know" that test is a string.

How does your second case work, then? You're performing a C-style cast from a derived to public base. Surprisingly, this is allowed (although not necessarily good style!). Quoting from the accepted answer there: §5.4/7 of the standard:

... the following static_cast and reinterpret_cast operations (optionally followed by a const_cast operation) may be performed using the cast notation of explicit type conversion, even if the base class type is not accessible: a pointer to an object of derived class type or an lvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;



Related Topics



Leave a reply



Submit