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 b
but 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.
” The same semantic restrictions and behaviors [as for a
static_cast
] apply [for a C style cast], with the exception that in performing astatic_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:
Outside of
test
(inmain
), you call theshow
method. That's OK, because it's public.Now, inside
show
, the code "knows" it's of typestring
, because it's a method oftest
. 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
Understanding the Dangers of Sprintf(...)
How to Set Visual Studio Filters for Nested Sub Directory Using Cmake
Lcov/Gcov Branch Coverage with C++ Producing Branches All Over the Place
Static Analysis Tool to Detect Abi Breaks in C++
Makefile: How to Correctly Include Header File and Its Directory
Using Createwindowex to Make a Message-Only Window
Why Is Copy Constructor Called Instead of Conversion Constructor
Will a "Variablename;" C++ Statement Be a No-Op at All Times
How Many Spaces for Tab Character(\T)
C++ Convert Integer to String at Compile Time
Do I Need to Close a Std::Fstream
How to Prevent Stack Allocation of an Object and Only Allow It to Be Instantiated with 'New'
Delayed Start of a Thread in C++ 11
Boolean Values as 8 Bit in Compilers. Are Operations on Them Inefficient
What Information Does Gcc Profile Guided Optimization (Pgo) Collect and Which Optimizations Use It