Why does Base *pd = new Derived; generate an error? - c++

Given this code:
class Base{
public:
Base();
virtual ~Base();
};
class Derived: protected Base{
public:
virtual ~Derived();
};
In main I am trying to assign derived to base in this way:
Base *pd = new Derived;
Why is this statement generating an error?
Here new will return a pointer of the object type and we can always assign a derived pointer to a base. Correct me if I am wrong.

To convert a pointer to one class to a pointer to a different class type the conversion must be accessible at the point that it is invoked.
As Base is a protected base of Derived you can't initialize a variable of type Base * from the expression new Derived (which has type Derived *) outside of a member function of Derived, a class derived from it or a friend of Derived.

A linker error may just be the result of missing an implementations for the classes. It would help if you could post the particular error messages.

Related

Access protected members of an existing base object

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.

using the return type as pointer to derived class

Is it possible to have a function in base class which will have return type as pointer to derived class? the main objective is for later use where you use Base and Derived Class to set values.
Base B1;
B1.SetName("nameOfBase");
Derived* D1 = B1.CreateDerived("DerivedFromBase");//CreateDerived method will be in class Base
D1->SetMinPoint(0,1);//this method will be implemented in derived class
D1->SetMaxPoint(4,4);//this method will be implemented in derived class
I am having problem in implementation, i did something like
class Base
{
public:
Base();
bool SetName(char*);//or SetName(string)
Derived* CreateDerived(char*); // or Derived* CreateDerived(string)
~Base();
protected:
char baseName[20];// or string baseName
Derived* derivedPtr[5];
};
class Derived: public Base
{
public:
Derived();
bool SetName(char*);//the name given in Derived* CreateDerived(char*) will be set here
~Derived();
};
when i try to do this and run the program i get errors like
// Derived* CreateDerived(char*); // or Derived* CreateDerived(string)
error C2143: syntax error: missing ';' before '*'
error C4430: missing type identifier: int assumed.
Yes, it's possible. It seems to be a somewhat questionable design, but there's nothing preventing you from doing it. You just need to declare class Derived before you refer to it:
class Derived; //forward declaration here
class Base
{
public:
Base();
bool SetName(char*);//or SetName(string)
Derived* CreateDerived(char*); // or Derived* CreateDerived(string)
~Base();
protected:
char baseName[20];// or string baseName
Derived* derivedPtr[5];
};
class Derived: public Base
{
public:
Derived();
bool SetName(char*); //don't forget semi-colon
~Derived();
};
And as #psur mentioned, you were also missing a semi-colon after SetName.
And I do strongly suggest using std::string instead of char* for strings in C++.
Can't you make your CreateDerived method pure virtual and override it in the derived classes? The return type of the method in the Base class would be Base, but the overridden method in the derived class could return the Derived instance you need. I think that is the Template Method-Pattern.
Your class inheritance should always behave like an is-a relation (Derived-Class is-a Base-Class). I think your design suggestion sort of undermines this rule.

Casting to base class validity

Say I have a class named Base and a class that derives from it called SuperBase. Given that add takes in a Base*, would either of these be valid:
SuperBase *super = new SuperBase;
bases.add(super);
Or
SuperBase *super = new SuperBase;
bases.add((Base*)super);
The first works as long as SuperBase publicly derives from Base, via an implicit conversion from derived-to-base:
struct base { virtual ~base() {} };
struct derived : base {};
base* b = new derived; // okay
The second works as well, but ignores the protection of Base:
struct derived : private base {}; // private base
base* b = new derived; // not okay, base is private
base* b = (base*)(new derived); // okay, but gross
If it's private, you probably shouldn't cast to it.
Both are valid - a child can be used in a place where a reference/pointer to parent is expected. This is called polymorphism.
Both would be valid, though type-casting super to Base* is not necessary.

Can a pointer of a derived class be type cast to the pointer of its base class?

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?

Protected derived class

#include <iostream>
using namespace std;
class Base
{
public:
Base(){cout <<"Base"<<endl;}
virtual ~Base(){cout<<"~Base"<<endl;}
virtual void foo(){ cout<<"foo base"<<endl;}
};
class Derived: private Base
{
public:
Derived(){cout<<"Derived"<<endl;}
virtual ~Derived(){cout<<"~Derived"<<endl;}
virtual void foo(){ cout<<"foo dervied"<<endl;}
};
int main(int argc, char *argv[])
{
Base *pb = new Derived;
Derived d;
d.foo();
return 0;
}
when I execute the above sample program I get following error:
protected.cpp: In function ‘int main(int, char**)’:
protected.cpp:26: error: ‘Base’ is an inaccessible base of ‘Derived’
Why its not possible to create Derived object with base pointer????
So I can create an instanse of Derived class like
Derived d
Derived d1= new Derived;
But creating instance from Base class pointer like
Base * b = new derived
will fail.
This is because Derived is not actaully a derived class from Base when derived procted and privately??
Is this correct?????
Why its not possible to create Derived object with base pointer????
Because the base is private. This explicitly forbids treating your class as a Base instance from the outside. Seen from the outside, your class Derived is not a subclass of Base, only from inside the class itself.
The same counts for protected inheritance, with the only difference that the base class now isn't private to the own class any more but rather to any derived class as well. To the outside though, it behaves just like private inheritance.
You might want to take a look at this faq on c++ and inheritance. Sections 24.5 and 24.6 in particular.
So I can create an instanse of Derived class like
Derived d Derived d1= new Derived; But
creating instance from Base class
pointer like
Base * b = new derived will fail.
This is because Derived is not
actaully a derived class from Base
when derived procted and privately??
Is this correct?????
It's exactly like Konrad explained.
It is in reality still derived from Base. To verify this, if you don't override the virtual methods in Derived then the Base versions will get called.
However, since you declared Base as protected the compiler won't let you automatically cast a Derived* to a Base* because the Base superclass is not visible externally.