class base{
.....
virtual void function1();
virtual void function2();
};
class derived::public base{
int function1();
int function2();
};
int main()
{
derived d;
base *b = &d;
int k = b->function1() // Why use this instead of the following line?
int k = d.function1(); // With this, the need for virtual functions is gone, right?
}
I am not a CompSci engineer and I would like to know this. Why use virtual functions if we can avoid base class pointers?
The power of polymorphism isn't really apparent in your simple example, but if you extend it a bit it might become clearer.
class vehicle{
.....
virtual int getEmission();
}
class car : public vehicle{
int getEmission();
}
class bus : public vehicle{
int getEmission();
}
int main()
{
car a;
car b;
car c;
bus d;
bus e;
vehicle *traffic[]={&a,&b,&c,&d,&e};
int totalEmission=0;
for(int i=0;i<5;i++)
{
totalEmission+=traffic[i]->getEmission();
}
}
This lets you iterate through a list of pointers and have different methods get called depending on the underlying type. Basically it lets you write code where you don't need to know what the child type is at compile time, but the code will perform the right function anyway.
You're correct, if you have an object you don't need to refer to it via a pointer. You also don't need a virtual destructor when the object will be destroyed as the type it was created.
The utility comes when you get a pointer to an object from another piece of code, and you don't really know what the most derived type is. You can have two or more derived types built on the same base, and have a function that returns a pointer to the base type. Virtual functions will allow you to use the pointer without worrying about which derived type you're using, until it's time to destroy the object. The virtual destructor will destroy the object without you knowing which derived class it corresponds to.
Here's the simplest example of using virtual functions:
base *b = new derived;
b->function1();
delete b;
its to implement polymorphism. Unless you have base class pointer
pointing to derived object you cannot have polymorphism here.
One of the key features of derived classes is that a pointer to a
derived class is type-compatible with a pointer to its base class.
Polymorphism is the art of taking advantage of this simple but
powerful and versatile feature, that brings Object Oriented
Methodologies to its full potential.
In C++, a special type/subtype relationship exists in which a base
class pointer or a reference can address any of its derived class
subtypes without programmer intervention. This ability to manipulate
more than one type with a pointer or a reference to a base class is
spoken of as polymorphism.
Subtype polymorphism allows us to write the kernel of our application
independent of the individual types we wish to manipulate. Rather, we
program the public interface of the base class of our abstraction
through base class pointers and references. At run-time, the actual
type being referenced is resolved and the appropriate instance of the
public interface is invoked. The run-time resolution of the
appropriate function to invoke is termed dynamic binding (by default,
functions are resolved statically at compile-time). In C++, dynamic
binding is supported through a mechanism referred to as class virtual
functions. Subtype polymorphism through inheritance and dynamic
binding provide the foundation for objectoriented programming
The primary benefit of an inheritance hierarchy is that we can program
to the public interface of the abstract base class rather than to the
individual types that form its inheritance hierarchy, in this way
shielding our code from changes in that hierarchy. We define eval(),
for example, as a public virtual function of the abstract Query base
class. By writing code such as
_rop->eval();
user code is shielded from the variety and volatility of our query language. This not only allows for the addition, revision,
or removal of types without requiring changes to user programs, but
frees the provider of a new query type from having to recode behavior
or actions common to all types in the hierarchy itself. This is
supported by two special characteristics of inheritance: polymorphism
and dynamic binding. When we speak of polymorphism within C++, we
primarily mean the ability of a pointer or a reference of a base class
to address any of its derived classes. For example, if we define a
nonmember function eval() as follows, // pquery can address any of the
classes derived from Query
void eval( const Query *pquery ) { pquery->eval(); }
we can invoke it legally, passing in the address of an object of any of the
four query types:
int main()
{
AndQuery aq;
NotQuery notq;
OrQuery *oq = new OrQuery;
NameQuery nq( "Botticelli" ); // ok: each is derived from Query
// compiler converts to base class automatically
eval( &aq );
eval( ¬q );
eval( oq );
eval( &nq );
}
whereas an attempt to invoke eval() with the address of an object not derived from Query
results in a compile-time error:
int main()
{ string name("Scooby-Doo" ); // error: string is not derived from Query
eval( &name);
}
Within eval(), the execution of pquery->eval(); must invoke the
appropriate eval() virtual member function based on the actual class
object pquery addresses. In the previous example, pquery in turn
addresses an AndQuery object, a NotQuery object, an OrQuery object,
and a NameQuery object. At each invocation point during the execution
of our program, the actual class type addressed by pquery is
determined, and the appropriate eval() instance is called. Dynamic
binding is the mechanism through which this is accomplished.
In the object-oriented paradigm, the programmer manipulates an unknown instance of a bound but infinite set of types. (The set of
types is bound by its inheritance hierarchy. In theory, however, there
is no limit to the depth and breadth of that hierarchy.) In C++ this
is achieved through the manipulation of objects through base class
pointers and references only. In the object-based paradigm, the
programmer
manipulates an instance of a fixed, singular type that is completely defined at the point of compilation. Although the
polymorphic manipulation of an object requires that the object be
accessed either through a pointer or a reference, the manipulation of
a pointer or a reference in C++ does not in itself necessarily result
in polymorphism. For example, consider
// no polymorphism
int *pi;
// no language-supported polymorphism
void *pvi;
// ok: pquery may address any Query derivation
Query *pquery;
In C++, polymorphism
exists only within individual class hierarchies. Pointers of type
void* can be described as polymorphic, but they are without explicit
language support — that is, they must be managed by the programmer
through explicit casts and some form of discriminant that keeps track
of the actual type being addressed.
You seem to have asked two questions (in the title and in the end):
Why use base class pointers for derived classes?
This is the very use of polymorphism. It allows you to treat objects uniformly while allowing you to have specific implementation. If this bothers you, then I assume you should ask: Why polymorphism?
Why use virtual destructors if we can avoid base class pointers?
The problem here is you cannot always avoid base class pointers to exploit the strength of polymorphism.
Related
I have two classes
class A {
public:
virtual void doStuff() = 0;
};
class B : public A {
int x;
public:
virtual void doStuff() override { x = x*2;} //just example function
};
And another class that modify and use data from the previous
class Foo {
A a;
public:
Foo::Foo(A &a_) : a(a_) {}
};
now I create the objects, and passes to the Foo class
B b;
// edit b attributes,
Foo foo(b);
So at the argument list for the class constructor I know there is not the problem of object slicing, because is a reference, but what is the case at the moment of assign the variable a(a_)?
Since I don't know how much time the object b is going to live I need to make a secure copy. I have a lot of different derived classes from A, even derived from the derived.
Will there be a object slicing?,
Is there a solution to this, or I need to pass pointers (don't want this approach)?
This causes slicing. C++ built in polymorphism only works with pointer/reference semantics.
In fact:
class Foo {
A a;
that won't even compile, because A is not a concrete class.
To fix this, first make virtual ~A(){}; and then pass smart pointers to A around. Either unique or shared.
Failing that you can use your own bespoke polymorphism. The easiers way is to stuff a pImpl smart pointer as a private member of a class and implement copy/move semantics in the holding class. The pImpl can have a virtual interface, and the wrapping class just forwards the non-overridable part of the behaviour to it.
This technique can be extended with the small buffer optimization, or even bounded size instances, in order to avoid heap allocation.
All of this is harder than just using the built in C++ object model directly, but it can have payoff.
To see a famous example of this, examine std::function<Sig> which is a value type that behaves polymorphically.
There will be object slicing with what you currently have. You're calling the A copy-constructor in Foo's constructor, and there aren't virtual constructors.
Having a member variable of type A only reserves enough space within an instance of Foo for an instance of A. There is only dynamic binding with pointers and references (which are pointers under the hood), not with member variables.
You would have to use pointers to get around this or you could rethink whether you really need a set-up like this.
Yes, there is slicing.
There has to be slicing, because a B does not fit inside a A, but it is an A that you are storing inside the class Foo. The B part is "sliced off" to fit; hence the name.
I couldn't find examples of is-a relationship without virtual functions. Is a following pattern ok?
class Base {
public:
void doSomethingWithX() {/*implementation here*/}
protected:
~Base(){}
private:
int x_;
};
class Derived : public Base {
//Add some other functionality but inherit doSomethingWithX and its implementaion
public:
void doSomethingWithY();
~Derived(); //And document that nobody should inherit further from this class.
private:
int y_;
};
foo(Base* ptr) {
//Do something via Base interface
}
Derived d;
foo(&d);
Edit: I was asked to clarify what I mean by "is this pattern ok".
Does this kind of inheritance satisfies what is usually needed from is-a relationship? Liskov substitution principle etc.
Is it safe to use Derived objects via pointer to Base? (or I miss some problem here).
I'm asking this because there is often written that base class destructor should be either public and virtual or protected and non-virtual. But I never met real examples of public inheritance without non-virtual functions.
It's okay for what you're doing here; You can pass a pointer to Derived and it can bind to a pointer of Base just fine. It's not possible to say whether it satisfies the Liskov subtitution principle because we do not know the invariants of your classes.
Just recognize that without any virtual functions, you cannot use polymorphism. This goes beyond simply overriding function behavior; you'll never be able to perform a dynamic_cast of a pointer to Base to a pointer to Derived.
Additionally, if nobody should derive from Derived, then mark it final, which is available since C++11
There are two types of polymorphism, both implementable in C++: static and dynamic. The latter is what you get with virtual functions and pointers to base classes, in which the behaviour is specialized depending on the real type of object pointed to.
The former can be achieved by writing a template, in which your template type is assumed to have certain interfaces. The compiler will then enforce that when instantiating the template, at compile time. You can provide additional enforcement using SFINAE and/or static_asserts to ensure the type used "is a" or rather conforms to the templated interface used by your code. Note there is not really a straightforward way of defining this interface as with a base interface class, aside from the aforementioned methods.
Note that static polymorphism is what you get at compile time. No dynamically chosen types at runtime. You'll need some form of base class for that.
I'm currently trying to make a pair of classes which depend on each other. Essentially, objects of class B create objects of class A. However, I am also using an inheritance hierarchy, so all derivatives of class B must also be able to create derivatives of class A (each derivative of B corresponds to a derivative of A, so DerB1 makes DerA1 objects, and DerB2 makes DerA2 objects).
I'm having problems with my implementation, and it may be silly, but I would like to see if anyone knows what to do. My code is below (I HATE reading other people's code, so I tried to make it as easy to read as possible...only a few important bits, which I commented to explain)
class BaseB {} // Declare BaseB early to use in BaseA constructor
class BaseA
{
public:
BaseA(BaseB* b) {}; // Declare the BaseA constructor (callable by all B classes, which pass a pointer to themselves to the constructor so the A objects can keep track of their parent)
}
class DerA:public BaseA
{
DerA(BaseB* b):BaseA(b) {}; // Inherit the BaseA constructor, and use initialization list
}
class BaseB
{
public:
virtual BaseA createA() = 0; // Virtual function, representing method to create A objects
}
class DerB:public BaseB
{
BaseA createA() {
DerA* a = new DerA(this); // Definition of createA to make a new A object, specifically one of type DerA (Error1: No instance of constructor "DerA::DerA" matches the argument list)
return a; // Error2: Cannot return DerA for BaseA function
}
}
So, I have two main problems, one is practical (Error1, as I seem to simply be calling the function wrong, even if I try to typecast this), one is philosophical (Error 2, as I don't know how to implement the features I want. If anyone could point out why Error1 is occurring, that would be wonderful! Error2, however, requires some explanation.
I would like my user (programmer) to interact with all A objects the same way. They will have the same exact public functions, but each will have VERY different implementations of these functions. Some will be using different data types (and so will require function contracts), but many will have the same data types just with different algorithms that they use on them. I would like some piece of code to work exactly the same way if one class A derivative is used or another is. However, in my current implementation, it seems that I need to return a DerA object instead of a BaseA object (at the site of Error2). This means that I will need to write a segment of main code SPECIFICALLY for a DerA object, instead of any arbitrary A object. I would like something like:
BaseB b = new DerB(); // Declare which derivative of BaseB I want to use
BaseA a = b->createA(b); // Call the createA function in that derivative, which will automatically make a corresponding A object
This way, I can simply choose which type of B object I would like in the first line (by my choice of B constructor, or tag, or template, or something), and the rest of the code will look the same for any type of object B (as each has the same public member functions, even though each object will perform those functions differently).
Would I be better off using templates or some other method instead of inheritance? (I apologize for being intentionally vague, but I hope my class A/B example should mostly explain what I need).
Thank you for any help. I apologize for asking two questions in one post and for being long-winded, but I am trying to learn the best way to approach a rather large redesign of some software.
You have several syntactical issues to get the errors solved:
Add the ; after each class definitions.
The first line should be a forward declaration: class BaseB /*{} NO!!*/ ;
Add public: to make constructor of DerA accessible for DerB
BaseA createA() should return a value, not a pointner (according to signature): return *a;
There is another potential hidden slicing issue, as createA() returns a value, an not a pointer. This means that your returned object (here *a), would be copied but as a real BaseA object. So only the BaseA part of the object will be copied, not the derived part. This could lead to some unexpected surprises.
In order to avoid slicing, consider returning a pointer, changing the signature of createA() accordingly. The object pointed to would then keep the right type without loosing anything.
If you would later need to copy the object, you could use a static cast if you are absolutely sure of the real type of the object pointed to:
BaseA *pba = pdb->createA(); // get pointer returned
DerA da = *static_cast<DerA*>(pba); // static cast with pointer
If you would need to copy pointed BaseA objects without necessarily knwowing for sure their real type, you could implement a virtual clone function in DerA (e.g. prototype design pattern)
I was studying Virtual Functions and Pointers. Below code made me to think about, why does one need Virtual Function when we can type cast base class pointer the way we want?
class baseclass {
public:
void show() {
cout << "In Base\n";
}
};
class derivedclass1 : public baseclass {
public:
void show() {
cout << "In Derived 1\n";
}
};
class derivedclass2 : public baseclass {
public:
void show() {
cout << "In Derived 2\n";
}
};
int main(void) {
baseclass * bptr[2];
bptr[0] = new derivedclass1;
bptr[1] = new derivedclass2;
((derivedclass1*) bptr)->show();
((derivedclass2*) bptr)->show();
delete bptr[0];
delete bptr[1];
return 0;
}
Gives same result if we use virtual in base class.
In Derived 1
In Derived 2
Am I missing something?
Your example appears to work, because there is no data, and no virtual methods, and no multiple inheritance. Try adding int value; to derivedclass1, const char *cstr; to derivedclass2, initialize these in corresponding constructors, and add printing these to corresponding show() methods.
You will see how show() will print garbage value (if you cast pointer to derivedclass1 when it is not) or crash (if you cast the pointer to derivedclass2 when class in fact is not of that type), or behave otherwise oddly.
C++ class member functions AKA methods are nothing more than functions, which take one hidden extra argument, this pointer, and they assume that it points to an object of right type. So when you have an object of type derivedclass1, but you cast a pointer to it to type derivedclass2, then what happens without virtual methods is this:
method of derivedclass2 gets called, because well, you explicitly said "this is a pointer to derivedclass2".
the method gets pointer to actual object, this. It thinks it points to actual instance of derivedclass2, which would have certain data members at certain offsets.
if the object actually is a derivedclass1, that memory contains something quite different. So if method thinks there is a char pointer, but in fact there isn't, then accessing the data it points to will probably access illegal address and crash.
If you instead use virtual methods, and have pointer to common base class, then when you call a method, compiler generates code to call the right method. It actually inserts code and data (using a table filled with virtual method pointers, usually called vtable, one per class, and pointer to it, one per object/instance) with which it knows to call the right method. So when ever you call a virtual method, it's not a direct call, but instead the object has extra pointer to the vtable of the real class, which tells what method should really be called for that object.
In summary, type casts are in no way an alternative to virtual methods. And, as a side note, every type cast is a place to ask "Why is this cast here? Is there some fundamental problem with this software, if it needs a cast here?". Legitimate use cases for type casts are quite rare indeed, especially with OOP objects. Also, never use C-style type casts with object pointers, use static_cast and dynamic_cast if you really need to cast.
If you use virtual functions, your code calling the function doesn't need to know about the actual class of the object. You'd just call the function blindly and correct function would be executed. This is the basis of polymorphism.
Type-casting is always risky and can cause run-time errors in large programs.
Your code should be open for extension but closed for modifications.
Hope this helps.
You need virtual functions where you don't know the derived type until run-time (e.g. when it depends on user input).
In your example, you have hard-coded casts to derivedclass2 and derivedclass1. Now what would you do here?
void f(baseclass * bptr)
{
// call the right show() function
}
Perhaps your confusion stems from the fact that you've not yet encountered a situation where virtual functions were actually useful. When you always know exactly at compile-time the concrete type you are operating on, then you don't need virtual functions at all.
Two other problems in your example code:
Use of C-style cast instead of C++-style dynamic_cast (of course, you usually don't need to cast anyway when you use virtual functons for the problem they are designed to solve).
Treating arrays polymorphically. See Item 3 in Scott Meyer's More Effective C++ book ("Never treat arrays polymorphically").
C++ supports inheritance.
But how is it implemented in the compiler?
Does the compiler copy and paste all the implementation from parent to child?
EXTREMELY simplified, if we are talking about something like this:
class A
{
public:
int func1() { do something; }
int func2() { do something; }
};
class B : public A
{
public:
int func2() { do somethign else; }
};
B b;
b.func1();
then what happens inside the compiler will be this (remember, this is VERY simplified, and the real compiler code will be a lot more complex, I'm sure):
... fname = "func1" from the source code ...
... object = "b";
function fn;
while (!(fn = find_func(object, fname)))
object = parent_object(object);
if (fn)
produce_call(fn);
else
print_error_not_found(fname);
If we are talking about virtual functions, then the compiler will produce a table which holds the address of the respective virtual function, and the table is generated for each class, based on a similar principle of "find the function that exists in a this class or one of its parents).
[In the above, I've ignored the fact that one class can have more than one "parent" class - it doesn't change how things works, just that the code has to maintain a list or array of "more classes at the same level"]
Just like member variables, base classes cause a subobject to be embedded inside all instances of the derived class. Member functions of the base class are not duplicated for the derived class, instead they are called on this subobject corresponding to the base class.
The compiler knows where this subobject is located relative to the full object, and will insert pointer arithmetic everywhere there is a cast (possibly implicit) between pointer (or reference) to derived and to base. This includes the hidden this-pointer arguments passed to member functions of the base type.
Virtual inheritance is a little bit tricky, because the offset can be different depending on the most-derived type. In that case, the compiler needs to store the offset as a variable inside the class instances so it can be looked up at runtime (just like pointers to virtual member functions, there might be another layer of indirection involved to save space).