Lets say I have a base class with protected member:
class Base
{
public:
Base(int data)
: m_attribute(data) {}
protected:
int m_attribute;
};
and derived class from base:
class Derived : public Base
{
public:
int get_attribute()
{
return m_attribute;
}
};
First of all: I can do this, right? Is this totally legal?
If yes, then here is the question:
I can't change anything in a Base class;
I have a Base class object, and I need to access its m_attribute member;
Should I do downcasting from this base class object to derived class object first, and then call get_attribute() function? Something like this:
Base base(5);
Derived* derived = static_cast < Derived*>(&base);
int base_attribute = derived->get_attribute();
Or what are other ways to access protected member? I know that friend function is an option, but I can't change anything in the base class
Should I do downcasting from this base class object to derived class object first, and then call get_attribute() function?
Most definitely not. An instance of a base class is not an instance of a derived class. Your conversion is ill-formed.
Here is a valid way:
struct kludge : Base {
kludge(const Base& b): Base(b) {}
operator int() {
return m_attribute;
}
};
usage:
Base base(5);
int foo = kludge(base);
This kludge works by copy constructing the base sub object of the derived type. This of course depends on the base being copyable - which your Base is. It's easy to tweak to work with movable as well.
As a syntactic sugar, the kludge is implicitly convertible to the type of the member. If you prefer, you could use a getter.
if base class doesn't have a default constructor after overloading it to take some arguments and no default one is there then the derived classes must use member-initializer list to initialize the base part otherwise you cannot instantiate the derived class getting the compiler complaining about missing default constructor in base class:
class Base
{
public:
// Base(){} default constructor by default the compiler creates one for you unless you overload it so the next one taking one parameter will hide this one
Base(int data) // hides the default ctor so derived classes must use member-initializer list
: m_attribute(data) {}
protected:
int m_attribute;
};
class Derived : public Base
{
public:
Derived() : Base(0){} // you must use member intializer list to initialize the part Base
//Derived(int x) : Base(x){} // also ok
int get_attribute(){ return m_attribute; }
};
int main()
{
Derived dervObj;
Derived* derived = static_cast < Derived*>(&baseObj);
int base_attribute = derived->get_attribute();
cout << base_attribute << endl;
}
also you cannot cast the address of class base to derived object but cast an object of base class to derived one.
so in your example writing in main:
Derived* derived = static_cast < Derived*>(&baseObj); // is like writing:
char* cp = static_cast < char*>(&int); // you must convert a variable not a type
why you want to access protected members from outside??? keep in mind that public inheritance will copy all the members of base to derived class but private.
using friendship or making member data public will make it possible to access it from outside but it undermines the principles of data-hiding and encapsulation however friendship in some cases it's a must and there's no other alternative then use it carefully but making data public it's better to get back to structs
The Derived class can access and modify the public and protected Base class properties and methods.
Then, you can't case Base into Derived.
Derived inherit from Base, so Derived is a Base.
But a Base is not a Derived (a Car is a Vehicle, a Vehicle is not a Car).
So if you need a getter, put it directly into Base, or instanciate a Derived instead of a Base.
Firstly:
Derived* derived = static_cast < Base*>(base);
This is not valid and illegal. Won't compile. You can't static cast Base to Base*.
And to answer your question:
Base base(5);
Derived& derived = static_cast<Derived&>(base);
std::cout << derived.get_attribute();
Or if you want to use a pointer because you think you're cooler:
Base base(5);
Derived* derived = static_cast<Derived*>(&base);
std::cout << derived->get_attribute();
EDIT: static_cast doesn't have any overhead on runtime. It is static, hence it's a compile-time thing. Both methods will yield the same result.
Related
I am currently trying to set a member of a class (myClass) to be some derived classes (Derived1, Derived2,...) of a Base class. Since the class don't know which derived class it is, the member type is set to Base class, it is only set to the derived class when constructed.
The derived classes all have a common member function which is implemented differently (Base class has a virtual version). However, when the this function is called from myClass, it always call the Base class version rather than the derived classes.
class Base
{
public:
Base(){}
virtual void who() { cout << "this is Base"; }
}
class Derived1 : public Base
{
public:
Derived1() : Base() {}
void who() { cout << "this is Derived1"; }
}
class myClass
{
private:
Base unknownDerived;
public:
myClass(const Base& inputDerived) { unknownDerived = inputDerived; }
void whosthere() { unknownDerived.who(); }
}
The output above is "this is Base", the Base class version is called instead.
Is there a way to include a member without specifying the actual derived class it is, but be able to call its specific function ( who() )?
thanks a lot!
When you declare Base as a member, Base is what you actually get. Even if you assign a Derived type to it, you experience what's called "slicing", where only the Base part of the derived object is copied, and your object is still a Base.
In C++, polymorphism only works through pointers and through references.
To make a real member object (not an indirection to the object) in myClass, you will need to make myClass have a template parameter, and you can decide at compile time what type it will be. Otherwise, you must use pointers and/or references.
Now you have to be clear about memory ownership, and proper cleanup. You may make the caller transfer the ownership of the object (by taking a unique_ptr) or you might insist that Base has a virtual clone() function to create a deep copy of the object. Further, you most likely will need a virtual destructor in your base class as well.
Say we have one base class and one derived class:
class Base {
string s1;
string s2;
...
string s100; // Hundreds of members
};
class Derived : public Base{
string s101;
};
I want to assign a Base object base to a Derived object derived. I know we can't just use operator "=" to assign a base object to its derived object.
My question is: Do we have to make copies of all the members one by one? Like:
derived.s1 = base.s1;
derived.s2 = base.s2;
...
derived.s100 = base.s100;
Is there any faster or more concise way to do this? Overload an operator= with
the returned base object?
I want to assign a Base object base to a Derived object derived.
Provide an overload operator= for it:
class Derived : public Base {
Derived& operator=(const Base& b) {
Base::operator=(b); // call operator= of Base
s101 = something; // set sth to s101 if necessary
return *this;
}
};
Then you can
Base b;
// ...
Derived d;
// ...
d = b;
I know we can't just use operator "=" to assign a base object to its
derived object.
Of course you can (in the context of this question):
static_cast<Base &>(derived)=base;
Stock example:
class Base {};
class Derived : public Base {};
void foo()
{
Derived d;
Base b;
static_cast<Base &>(d)=b;
}
I know we can't just use operator "=" to assign a base object to its derived object
That's not true.
Do we have to make copies of all the members one by one? Like:
base.s1 = derived.s1;
base.s2 = derived.s2;
...
base.s100 = derived.s100;
Not really. As mentioned in the first comment by Danh.
base = derived
is enough, since it performs implicit dynamic upcast (i.e. converting from pointer-to-derived to pointer-to-base). See http://www.cplusplus.com/doc/tutorial/typecasting/
class base{
private:
int a;
public:
int b;
void setData(){
a = 10; b = 5;
}
};
class derived: public base{
private:
int c;
public:
// b is inherited
};
void main(){
derived D1;
D1.setData();
}
I learned that private members aren't inherited. So, the private variable a (in the base class) is not present in the derived class object. My question is when D1.setData() is called, how can it assign a value to a, if a doesn't exist?
I'm pretty sure I have this concept wrong, so can some one explain how this works? Are the base class members also created when the derived class object is created?
I learned that private members aren't inherited.
Of course they are inherited: otherwise, all member functions of the base class that need these private variables would be broken. Although private members are not accessible to the inheriting class, the base class retain full access to them.
Can some one explain how this works?
Layout of the inheriting class derived includes a place to store a, the private member of the base class. All methods of the base class can access base::a. At the same time, it remains inaccessible to the derived class: any attempt to access a from derived would cause a compile-time error.
Private member variables are inherited, but cannot be accessed externally. The memory pattern of inheritance is simple:
class base {
int x;
};
class subclassCpp : public base {
int y;
};
class subclassCStyle {
base a;
int y;
};
Now, subclassCpp and subclassCStyle have the exact same memory pattern, regardless of private/protected status, etc. This should illustrate how the memory is laid out.
For the other question, "Are the base class members also created when the derived class object is created?"
The answer is yes, a constructor is always invoked on the base class. If you don't add this yourself, the default constructor is automatically invoked. If the base class doesn't have a default constructor, it won't let you create a subclass constructor that doesn't properly invoke whatever constructor is necessary to initialize the base. So there is no legal way you can end up with a base class that hasn't been initialized when the subclass was created, as long as a constructor in the subclass was executed.
I have a class Derived which is derived from class Base. In Derived's function, I can access protected members of Base. E.g., I can do this.
class Base
{
protected:
int i;
}
class Derived : class Base
{
void process()
{
i = 5;
}
}
My question is, is it possible to enforce the use of scope resolution operator when accessing base class member from derived class? The reason is that I want to make it clear in the code which variables are from the base class. The enforcement is so that I won't accidentally skip the scope resolution operator (I'm careless). I prefer not to use accessors since many members from the base class are required in the Derived class, making it tedious to code. I'm using MSVC 2010 by the way.
class Base
{
protected:
int i;
}
class Derived : class Base
{
void process()
{
Base::i = 5; //enforce so that i=5 won't compile
}
}
you can simulate it by introducing another scope:
class Base {
protected:
struct Data {int i;};
Data d_Base;
};
class Derived : class Base {
void process() {
d_Base.i = 5;
}
};
You cannot do it in the base class itself, no, there is no way you could enforce that. However, I am thinking of a trick which you could do in a derived class to enforce what you want, that is, if you declare a variable with the same name i in the derived class as a member, but of type, say, MyBadType, which is just an empty type, then i in derived will refer to it and there is really nothing the user could do with it. So he will HAVE TO qualify to get the base i. But this is naturally a joke, I mean, you don't want to fatten the size of your derived class just to enforce qualified names. Your goal itself is a bit dubious.
HTH,
Armen
The pointer of derived class returned by new can be type cast to the pointer of its base class.
Is this true or false?
I know dynamic_cast can be used to cast downside. Generally, how to cast a pointer of derived class to a pointer of its base class?
Yes. Conversion from a pointer to a derived class to a pointer to a base class is implicit. Thus, the following is perfectly fine:
struct B { };
struct D : B { };
D* my_d_ptr = new D;
B* my_d_ptr_as_a_b_ptr = my_d_ptr;
Casting a pointer to a derived to a pointer to base should be implicit. This is the whole point of polymorphism: An instance of a derived class should always be safely usable as an instance of the base class. Therefore, no explicit cast is necessary.
That's true if derived class inherits 'publicly' and 'non-virtually' from base:
You can't convert Derived* to Base* neither implicitly nor using static_cast/dynamic_cast (C-cast will do the job, but you should think twice before use this hack!);
class Base { };
class Derived : protected Base { };
int main()
{
Base* b = new Derived(); // compile error
}
Also don't work if base class is ambiguous:
class Base { };
class Derived1 : public Base { };
class Derived2 : public Base { };
class MostDerived : public Derived1, Derived2 { };
int main()
{
Base* b = new MostDerived(); // won't work (but you could hint compiler
// which path to use for finding Base
}
Edit: added code samples, added ambiguous use case, removed virtual inheritance example.
Your question is not clear becuse it mixes up several different things.
On the one hand, a pointer to derived class can be converted to a pointer to a base class (assuming the base is accessible). This is a natural conversion and there's no need for any cast to do it.
On the other hand, you mention dynamic_cast and its ability to to perform downcasts. But downcasts are casts in the opposite direction: from a pointer to a base class to a pointer to derived class. Downcasts can be performed by both dynamic_cast and static_cast depending on what you need and what amount of run-time checking you require.
... And at the same time you ar talking about casting the result of new, which, of course, can only be upcasted, but not downcasted.
So, what is it you are asking about? Upcasts or downcasts?