Update: This issue is caused by bad memory usage, see solution at the bottom.
Here's some semi-pseudo code:
class ClassA
{
public:
virtual void VirtualFunction();
void SomeFunction();
}
class ClassB : public ClassA
{
public:
void VirtualFunction();
}
void ClassA::VirtualFunction()
{
// Intentionally empty (code smell?).
}
void ClassA::SomeFunction()
{
VirtualFunction();
}
void ClassB::VirtualFunction()
{
// I'd like this to be called from ClassA::SomeFunction()
std::cout << "Hello world!" << endl;
}
The C# equivalent is as follows: Removed C# example, as it's not relevant to the actual problem.
Why isn't the ClassB::VirtualFunction function being called when called from ClassA::SomeFunction? Instead ClassA::VirtualFunction is being called...
When I force implementation of the virtual function ClassA::VirtualFunction, like so:
class ClassA
{
public:
virtual void VirtualFunction() = 0;
void SomeFunction();
}
class ClassB : public ClassA
{
public:
void VirtualFunction();
}
void ClassA::SomeFunction()
{
VirtualFunction();
}
void ClassB::VirtualFunction()
{
// I'd like this to be called from ClassA::SomeFunction()
std::cout << "Hello world!" << endl;
}
The following error occurs at runtime, despite the derrived function deffinately being declared and defined.
pure virtual method called
terminate called without an active exception
Note: It seems like the error can be caused even by bad memory usage. See self-answer for details.
Update 1 - 4:
Comments removed (not releavnt).
Solution:
Posted as an answer.
class Base {
public:
virtual void f() { std::cout << "Base" << std::endl; }
void call() { f(); }
};
class Derived : public Base {
public:
virtual void f() { std::cout << "Derived" << std::endl; }
};
int main()
{
Derived d;
Base& b = d;
b.call(); // prints Derived
}
If in the Base class you do not want to implement the function you must declare so:
class Base {
public:
virtual void f() = 0; // pure virtual method
void call() { f(); }
};
And the compiler won't allow you to instantiate the class:
int main() {
//Base b; // error b has a pure virtual method
Derived d; // derive provides the implementation: ok
Base & b=d; // ok, the object is Derived, the reference is Base
b.call();
}
As a side note, be careful not to call virtual functions from constructors or destructors as you might get unexpected results.
If you're getting that 'pure virtual method called
terminate called without an active exception' error message, that means you're calling the virtual function from the constructor or destructor of classA (the base class), which you should not do.
on the pure virtual method called error:
You should create a different question as it is in fact different than the other. The answer to this question is on the very last paragraph of my previous answer to your initial question:
Do not call virtual functions from constructors or destructors
class Base
{
public:
Base() { f(); }
virtual void f() = 0;
};
class Derived : public Base
{
public:
virtual void f() {}
};
int main()
{
Derived d; // crashes with pure virtual method called
}
The problem in the code above is that the compiler will allow you to instantiate an object of type Derived (as it is not abstract: all virtual methods are implemented). The construction of a class starts with the construction of all the bases, in this case Base. The compiler will generate the virtual method table for type Base, where the entry for f() is 0 (not implemented in base). The compiler will execute the code in the constructor then. After the Base part has completely been constructed, construction of the Derived element part starts. The compiler will change the virtual table so that the entry for f() points to Derived::f().
If you try calling the method f() while still constructing Base, the entry in the virtual method table is still null and the application crashes.
When A calls VirtualFunction() it will automatically call the version on B. That is the point of virtual functions.
I am not as familiar with the C++ syntax tho. Do you have to declare the function to be virtual at the point of the body as well as in the header?
Alsop, in class B you probably need to mark it as override
in C# its easy. I just don't know the c++ syntax.
public class ClassA
{
public **virtual** void VirtualFunction(){}
public void FooBar()
{
// Will call ClassB.VirtualFunction()
VirtualFunction();
}
}
public class ClassB
{
public **overide** void VirtualFunction()
{
// hello world
}
}
If you want to force the derived classes to implement the VirtualFunction:
class ClassA
{
public:
virtual void VirtualFunction()=0;
void SomeFunction();
}
This is C++. Default the derived function will be called.
If you want to call the base-class function do:
void ClassA::SomeFunction()
{
// ... various lines of code ...
ClassA::VirtualFunction();
}
There's nothing wrong with your code but your sample is incomplete. You do not state where you are calling SomeFunction from.
As has already been pointed out by dribeas you must be careful calling virtual functions from your constructor as the virtual tables are only built up as each class in the hierarchy completes construction.
Edit: The following paragraph of my reply was incorrect. Apologies. It is fine to call SomeFunction from the constructor of ClassB as the vtable is in place (at least) by the end of the initialiser list i.e. once you are in the body of the constructor. It is not fine to call it from ClassA's constructor of course.
Original paragraph:
I suspect you must be calling SomeFunction from the constructor of ClassB at which point only the vtable up to type ClassA will be complete i.e. to the virtual dispatch mechanism your class is still of type ClassA. It only becomes an object of type ClassB when the constructor completes.
To call a virutal function function you need to call via a pointer or a reference.
void ClassA::SomeFunction()
{
VirtualFunction(); // Call ClassA::VirtualFunction
this->VirtualFunction(); // Call Via the virtual dispatch mechanism
// So in this case call ClassB::VirtualFunction
}
You need to be able to distinguish the two different types of call otherwise the classA::VirtualFunction() becomes inaccessible when it is overridden.
As pointed out by others if you want to make the base class version abstract then use the = 0 rather than {}
class A
{
virtual void VirtualFunction() =0;
....
But sometimes it is legitimate to have an empty definition. This will depend on your exact usage.
You aren't defining the function in ClassB correctly, it should be:
public class ClassB
{
public void override AbstractFunction()
{
// hello world
}
}
Then, any call from the base class to virtual/abstract methods will call the implementation on the derived instance.
Related
class Base
{
public:
int a;
virtual void fun1()
{
cout<<"Hello Base"<<endl;
}
void fun2()
{
fun1();
}
};
class Derived: public Base
{
int a;
void fun1()
{
cout<<"Hello Derived"<<endl;
}
};
int main()
{
Base * B = new Derived;
B->fun2();
return 1;
}
Please help me understand why output is Hello Derived.How this function binding takes place.How is virtual table entry created for Base and derived class.
The virtual table is created when the class objects are constructed. When you construct a Derived object, it will first call the Base constructor (which creates the vtable and writes its own Base::fun1 into that. Then the Derived constructor runs and overwrites the vtable entry for fun1 with its own implementation (Derived::fun1).
If you then, at any later point (even from within any Base function) call fun1 of such an object instance, it will look into the vtable and call whatever function it finds there. As explained above, it is Derived::fun1 that is in the vtable of a Derived object after construction, so this is the one that will get called. It doesn't matter that you are currently in a Base function, the vtable entry does not change.
Note that during construction, the vtable is not fully set up: If you were to call fun1 from within the Base constructor, you would not call Derived::fun1 but Base::fun1 because Derived did not replace the vtable entries yet.
Also note that fully specifying the function (e.g. calling Base::fun1() on a Derived instance) will not do a vtable lookup but instead use exactly the specified function.
The pseudo code looks like this:
#include <iostream>
class Base{
protected:
void **vt_ptr;
public:
int a;
//Executed prior to base member initialization
//and reexecuted prior to Base destructor call
void set_dynamic_type(){
vt_ptr = Base::vtable;
}
/*virtual*/
void fun1(){
reinterpret_cast<void(*)(Base&)>(vt_ptr[1])(*this);
}
void fun2(){
fun1();
}
private:
static void func1_def(Base& pseudo_obj_arg){
Base* this=&pseudo_obj_arg;
std::cout<<"Hello Base"<<std::endl;
}
static void* vtable[2];
};
void* Base::vtable[2]={
reinterpret_cast<void*>(&type_id_of_Base),
reinterpret_cast<void*>(&Base::func1_def)};
class Derived: public Base
{
int a;
//Executed after Base intialization,
//before Derived member initialization.
//Reexecuted prior to Derived destructor call
void set_dynamic_type(){
Base::vt_ptr = Derived::vtable;
}
private:
static void func1_def(Base& pseudo_obj_arg){
Derived* this=static_cast<Derived*>(&pseudo_obj_arg);
std::cout<<"Hello Derived"<<std::endl;
}
static void* vtable[2];
};
void* Derived::vtable[2]={
reinterpret_cast<void*>(&type_id_of_Derived),
reinterpret_cast<void*>(&Derived::func1_def)};
Also a qualified call as in: obj.Base::func1() directly calls Base::func1_def(obj), otherwise it goes throw the devirtualization process described in Base::func1.
class Base {
public:
virtual void f();
void f(int);
virtual ~Base();
};
class Derived : public Base {
public:
void f();
};
int main()
{
Derived *ptr = new Derived;
ptr->f(1);
delete ptr;
return 0;
}
ptr->f(1); is showing the following error: "too many arguments in function call".
Why is this isn't possible? isn't derived inherited all the functions form base and is free to use any of them?
I could call it explicitly and it would work but why isn't this allowed?
What you are seeing is called hiding.
When you override the function void f() in the Derived class, you hide all other variants of the f function in the Base class.
You can solve this with the using keyword:
class Derived : public Base {
public:
using Base::f; // Pull all `f` symbols from the base class into the scope of this class
void f() override; // Override the non-argument version
};
As mentioned by #Some Programming Dude : it is because of Hiding.
To understand hiding in relatively simpler language
Inheritance is meant to bring Baseclass variables / functions in Derived class.
But, on 1 condition : "If its not already available in Derived Class"
Since f() is already available in Derived, it doesn't make sense to look at Base class from compiler perspective.
That's the precise reason why you need to scope clarify while calling this function
void main()
{
Derived *ptr = new Derived;
ptr->Base::f(1);
delete ptr;
}
Suppose for time being that Derived do have the access to the function void Base::f(int);. Then it will be a case of function overloading. But, this is invalid case of function overloading since one function f(int);is in Base and other function f(); is in Derived. Function Overloading happens inside a single class. Function Overriding happens across classes. The example you posted is a case of Name Hiding in Inheritance
"Derived *ptr" This definition will only allow "ptr" to access all the member functions which are defined via Derived class or its child class. But, it will not allow u to access the member functions which are coming in Derived class because of inheritance.
If u want to access base class version of function "f" then use "Base *ptr" and it will choose the correct version of function automatically as shown :)
class Base {
public:
virtual void f()
{
cout<<"Here 2"<<endl;
}
void f(int x)
{
cout<<"Here 1"<<endl;
}
virtual ~Base() {}
};
class Derived : public Base {
public:
void f()
{
cout<<"Here 3"<<endl;
}
virtual ~Derived() {}
};
int main()
{
Base *ptr = new Derived;
ptr->f(1);
delete ptr;
return 0;
}
output is
Here 1
Wikipedia has the following example on the C++11 final modifier:
struct Base2 {
virtual void f() final;
};
struct Derived2 : Base2 {
void f(); // ill-formed because the virtual function Base2::f has been marked final
};
I don't understand the point of introducing a virtual function and immediately marking it as final. Is this simply a bad example, or is there more to it?
Typically final will not be used on the base class' definition of a virtual function. final will be used by a derived class that overrides the function in order to prevent further derived types from further overriding the function. Since the overriding function must be virtual normally it would mean that anyone could override that function in a further derived type. final allows one to specify a function which overrides another but which cannot be overridden itself.
For example if you're designing a class hierarchy and need to override a function, but you do not want to allow users of the class hierarchy to do the same, then you might mark the functions as final in your derived classes.
Since it's been brought up twice in the comments I want to add:
One reason some give for a base class to declare a non-overriding method to be final is simply so that anyone trying to define that method in a derived class gets an error instead of silently creating a method that 'hides' the base class's method.
struct Base {
void test() { std::cout << "Base::test()\n"; }
};
void run(Base *o) {
o->test();
}
// Some other developer derives a class
struct Derived : Base {
void test() { std::cout << "Derived::test()\n"; }
};
int main() {
Derived o;
o.test();
run(&o);
}
Base's developer doesn't want Derived's developer to do this, and would like it to produce an error. So they write:
struct Base {
virtual void test() final { ... }
};
Using this declaration of Base::foo() causes the definition of Derived to produce an error like:
<source>:14:13: error: declaration of 'test' overrides a 'final' function
void test() { std::cout << "Derived::test()\n"; }
^
<source>:4:22: note: overridden virtual function is here
virtual void test() final { std::cout << "Base::test()\n"; }
^
You can decide if this purpose is worthwhile for yourself, but I want to point out that declaring the function virtual final is not a full solution for preventing this kind of hiding. A derived class can still hide Base::test() without provoking the desired compiler error:
struct Derived : Base {
void test(int = 0) { std::cout << "Derived::test()\n"; }
};
Whether Base::test() is virtual final or not, this definition of Derived is valid and the code Derived o; o.test(); run(&o); behaves exactly the same.
As for clear statements to users, personally I think just not marking a method virtual makes a clearer statement to users that the method is not intended to be overridden than marking it virtual final. But I suppose which way is clearer depends on the developer reading the code and what conventions they are familiar with.
For a function to be labelled final it must be virtual, i.e., in C++11 ยง10.3 para. 2:
[...] For convenience we say that any virtual function overrides itself.
and para 4:
If a virtual function f in some class B is marked with the virt-specifier final and in a class D derived from
B a function D::f overrides B::f, the program is ill-formed. [...]
i.e., final is required to be used with virtual functions (or with classes to block inheritance) only. Thus, the example requires virtual to be used for it to be valid C++ code.
EDIT: To be totally clear: The "point" asked about concerns why virtual is even used. The bottom-line reason why it is used is (i) because the code would not otherwise compile, and, (ii) why make the example more complicated using more classes when one suffices? Thus exactly one class with a virtual final function is used as an example.
It doesn't seem useful at all to me. I think this was just an example to demonstrate the syntax.
One possible use is if you don't want f to really be overrideable, but you still want to generate a vtable, but that is still a horrible way to do things.
Adding to the nice answers above - Here is a well-known application of final (very much inspired from Java). Assume we define a function wait() in a Base class, and we want only one implementation of wait() in all its descendants. In this case, we can declare wait() as final.
For example:
class Base {
public:
virtual void wait() final { cout << "I m inside Base::wait()" << endl; }
void wait_non_final() { cout << "I m inside Base::wait_non_final()" << endl; }
};
and here is the definition of the derived class:
class Derived : public Base {
public:
// assume programmer had no idea there is a function Base::wait()
// error: wait is final
void wait() { cout << "I am inside Derived::wait() \n"; }
// that's ok
void wait_non_final() { cout << "I am inside Derived::wait_non_final(); }
}
It would be useless (and not correct) if wait() was a pure virtual function. In this case: the compiler will ask you to define wait() inside the derived class. If you do so, it will give you an error because wait() is final.
Why should a final function be virtual? (which is also confusing) Because (imo) 1) the concept of final is very close to the concept of virtual functions [virtual functions has many implementations - final functions has only one implementation], 2) it is easy to implement the final effect using vtables.
I don't understand the point of introducing a virtual function and immediately marking it as final.
The purpose of that example is to illustrate how final works, and it does just that.
A practical purpose might be to see how a vtable influences a class' size.
struct Base2 {
virtual void f() final;
};
struct Base1 {
};
assert(sizeof(Base2) != sizeof(Base1)); //probably
Base2 can simply be used to test platform specifics, and there's no point in overriding f() since it's there just for testing purposes, so it's marked final. Of course, if you're doing this, there's something wrong in the design. I personally wouldn't create a class with a virtual function just to check the size of the vfptr.
While refactoring legacy code (e.g. removing a method that is virtual from a mother class), this is useful to ensure none of the child classes are using this virtual function.
// Removing foo method is not impacting any child class => this compiles
struct NoImpact { virtual void foo() final {} };
struct OK : NoImpact {};
// Removing foo method is impacting a child class => NOK class does not compile
struct ImpactChildClass { virtual void foo() final {} };
struct NOK : ImpactChildClass { void foo() {} };
int main() {}
Here is why you might actually choose to declare a function both virtual and final in a base class:
class A {
void f();
};
class B : public A {
void f(); // Compiles fine!
};
class C {
virtual void f() final;
};
class D : public C {
void f(); // Generates error.
};
A function marked final has to be also be virtual. Marking a function final prevents you from declaring a function with the same name and signature in a derived class.
Instead of this:
public:
virtual void f();
I find it useful to write this:
public:
virtual void f() final
{
do_f(); // breakpoint here
}
protected:
virtual void do_f();
The main reason being that you now have a single place to breakpoint before dispatching into any of potentially many overridden implementations. Sadly (IMHO), saying "final" also requires that you say "virtual."
I found another case where for virtual function is useful to be declared as final. This case is part of SonarQube list of warnings. The warning description says:
Calling an overridable member function from a constructor or destructor could result in unexpected behavior when instantiating a subclass which overrides the member function.
For example:
- By contract, the subclass class constructor starts by calling the parent class constructor.
- The parent class constructor calls the parent member function and not the one overridden in the child class, which is confusing for child class' developer.
- It can produce an undefined behavior if the member function is pure virtual in the parent class.
Noncompliant Code Example
class Parent {
public:
Parent() {
method1();
method2(); // Noncompliant; confusing because Parent::method2() will always been called even if the method is overridden
}
virtual ~Parent() {
method3(); // Noncompliant; undefined behavior (ex: throws a "pure virtual method called" exception)
}
protected:
void method1() { /*...*/ }
virtual void method2() { /*...*/ }
virtual void method3() = 0; // pure virtual
};
class Child : public Parent {
public:
Child() { // leads to a call to Parent::method2(), not Child::method2()
}
virtual ~Child() {
method3(); // Noncompliant; Child::method3() will always be called even if a child class overrides method3
}
protected:
void method2() override { /*...*/ }
void method3() override { /*...*/ }
};
Compliant Solution
class Parent {
public:
Parent() {
method1();
Parent::method2(); // acceptable but poor design
}
virtual ~Parent() {
// call to pure virtual function removed
}
protected:
void method1() { /*...*/ }
virtual void method2() { /*...*/ }
virtual void method3() = 0;
};
class Child : public Parent {
public:
Child() {
}
virtual ~Child() {
method3(); // method3() is now final so this is okay
}
protected:
void method2() override { /*...*/ }
void method3() final { /*...*/ } // this virtual function is "final"
};
virtual + final are used in one function declaration for making the example short.
Regarding the syntax of virtual and final, the Wikipedia example would be more expressive by introducing struct Base2 : Base1 with Base1 containing virtual void f(); and Base2 containing void f() final; (see below).
Standard
Referring to N3690:
virtual as function-specifier can be part of decl-specifier-seq
final can be part of virt-specifier-seq
There is no rule having to use the keyword virtual and the Identifiers with special meaning final together. Sec 8.4, function definitions (heed opt = optional):
function-definition:
attribute-specifier-seq(opt) decl-specifier-seq(opt) declarator virt-specifier-seq(opt) function-body
Practice
With C++11, you can omit the virtual keyword when using final. This compiles on gcc >4.7.1, on clang >3.0 with C++11, on msvc, ... (see compiler explorer).
struct A
{
virtual void f() {}
};
struct B : A
{
void f() final {}
};
int main()
{
auto b = B();
b.f();
}
PS: The example on cppreference also does not use virtual together with final in the same declaration.
PPS: The same applies for override.
I think most of the answers miss an important point. final means no more override after it has been specified. Marking it on a base class is close to pointless indeed.
When a derived class might get derived further, it can use final to lock the implementation of a given method to the one it provided.
#include <iostream>
class A {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
class B : public A {
public:
void foo() final override { std::cout<<"B::foo()"<<std::endl; }
void bar() override { std::cout<<"B::bar()"<<std::endl; }
};
class C : public B {
public:
// can't do this as B marked ::foo final!
// void foo() override { std::cout<<"C::foo()"<<std::endl; }
void bar() override { std::cout<<"C::bar()"<<std::endl; }
};
In Java it's possible to write an abstract, super class with unimplemented, abstract methods and non-abstract methods which invoke the abstract methods. Then in the subclass are the abstract methods implemented. When you then make an instance of the subclass, the super class uses the implementations in the subclass. How do I accomplish this in C++?
Here is what I mean, but in Java:
SuperClass.java
public abstract class SuperClass {
public SuperClass() {
method();
}
private void method() {
unimplementedMethod();
}
protected abstract void unimplementedMethod();
}
SubClass.java
public class SubClass extends SuperClass {
public SubClass() {
super();
}
#Override
protected void unimplementedMethod() {
System.out.println("print");
}
public static void main(String[] args) {
new SubClass();
}
}
Would be awesome if you showed me how this is accomplished in C++. :)
In general, what you are looking for, is the virtual keyword. In a nutshell virtual declares the intent that this method can be overriden. Note that such a method can still have an implementation- virtual just makes it overrideable. To declare an "abstract method", you can say declare intent of please provide an implementation in the derived class with = 0, as shown below. Such methods are called pure virtual in C++.
However, there are some caveats that you should watch out for. As pointed out in a comment below, you were calling method() from within the SuperClass constructor. Unfortunately this is not possible in C++, due to the order in which objects are constructed.
In C++ a derived class constructor immediately calls it's superclass constructor before allocating its members or executing the body of the constructor. As such, the members of the base class are constructed first, and the derived class' members are constructed last. Calling a virtual method from a base class will not work as you expect in Java, since the derived class has not been constructed yet, and thus the virtual methods have not been redirected to the derived implementations yet. Hope that makes sense.
However, calling method() on a SuperClass object after creation will work as you expect: it would call the virtual function which would output "print".
class SuperClass {
public:
SuperClass() {
// cannot call virtual functions from base constructor.
}
virtual ~SuperClass() { } // destructor. as Kerrek mentions,
// classes that will be inherited from,
// should always have virtual destructors.
// This allows the destructors of derived classes
// to be called when the base is destroyed.
private:
void method() {
unimplementedMethod();
}
protected:
virtual void unimplementedMethod() = 0; // makes method pure virtual,
// to be implemented in subclass
}
SubClass.h
class SubClass : public SuperClass {
public:
SubClass() : SuperClass() { // how the superclass constructor is called.
}
// no need for "override" keyword, if the methd has the same name, it will
// automatically override that method from the superclass
protected:
void unimplementedMethod() {
std::cout << "print" << std::endl;
}
}
In C++, you should never call virtual functions in the constructor, so it doesn't work quite as literally. Best to use a separate member function
class SuperClass
{
public:
void action() { method(); } // not in the constructor, please
virtual ~SuperClass() { } // always a virtual destructor when polymorphic
protected:
void method() { unimplementedMethod(); }
private:
virtual void unimplementedMethod() = 0;
};
class SubClass : public SuperClass
{
private:
virtual void unimplementedMethod() { std::cout << "print" << std::endl; }
// no need to spell out the next couple of functions, but for your entertainment only
public:
SubClass() : SuperClass() { }
virtual ~SubClass() { }
};
Now to invoke:
int main()
{
SuperClass * p = new SubClass; // construct first...
p->action(); // ... then invoke, after construction is complete
delete p; // thank god for that virtual destructor!
}
The base constructor runs before the derived class is constructed, so you cannot call any derived functions in the base constructor, and in particular you cannot call any pure-virtual functions.
Note that you have the private and protected the wrong way round: The non-virtual accessor function should be protected so it can be used in the entire class hierarchy, but the virtual implementation function should be private, since it only needs to be seen by the accessor function in the same class. In a nutshell: protected-nonvirtual and private-virtuals.
(The usage example is a bit contrived, since you wouldn't normally use new or raw pointers in C++.)
In C++ these are called pure virtual functions/methods.
Basically you tack a "=0" at the end of a method:
virtual doSomething() = 0; // pure virtual
Search around SO for "c++ pure virtual" and you'll find tons of answers.
You need to use virtual methods. The implementation works like this:
/* here's MyBaseClass.h */
class MyBaseClass
{
public:
MyBaseClass(void);
~MyBaseClass(void);
void MyMethod();
protected:
virtual void MyUnimplementedMethod() = 0;
};
/* here's MyIneritedClass.h */
class MyInheritedClass :
public MyBaseClass
{
public:
MyInheritedClass(void);
~MyInheritedClass(void);
protected:
virtual void MyUnimplementedMethod();
};
/* here's the implementation of the method in the base class */
void MyBaseClass::MyMethod()
{
MyUnimplementedMethod();
}
/* and here's the implementation of the abstract method in the derived */
void MyInheritedClass::MyUnimplementedMethod()
{
_tprintf(L"Hello, world");
}
You declare the method as virtual:
snippet:
class Parent{
public:
virtual int methodA() {return methodB();}; // calls the abstract method
virtual int methodB() = 0; // "=0" means pure virtual, not implemented in the base
}
class Child : public Parent{
public:
virtual int methodB() { /* implementation */}
}
virtual means the child may override the implementation and the parent should be then calling the overriden implementation. Adding "=0" to the declaration of the virtual method makes it pure virtual, i.e.: the base doesn't have an implementation of its own, and relies on the implementation by the child. Such class cannot be instantiated (i.e.: abstract class).
class base
{
public:
virtual void start();
virtual void stop();
void doSomething() { start(); .... stop(); }
}
class derived : public base
{
public:
void start();
void stop();
}
But when I call doSomething() in the derived class it is using it's own definition of Start() and Stop() - not the derived ones.
I don't want to rewrite doSomething() in the derived class because it would be identical to the base one. What am I doing wrong?
Sorry if that wasn't clear.
The behaviour of Start() and Stop() in the derived class is different (it's a different machine) - but I want to use the original base class doSomething() because that hasn't changed. It just has to start() and stop() using the new derived class code.
The code you've posted should work the way you want. Calling doSomething on an instance of derived will call the overridden start and stop functions defined in derived.
There's an exception to that, though. If you call doSomething in the constructor or destructor of base (whether directly or indirectly), then the versions of start and stop that get called will be the ones defined in base. That's because in those circumstances, you don't actually have a valid derived instance yet. It's either not fully constructed or partially destructed, so the language prevents you from calling methods that would use the partial object.
If you're not calling it from a base constructor or destructor, then there is more to the problem than what's shown here.
Update
Based on your comment below that you are trying to make doSomething() call the Derived class's version of start() and stop(), my updated answer to your question is as follows:
There is nothing wrong with the way that you defined Base and Derived. You are probably experiencing what is called "code slicing", where you are calling "doSomething()" on an object whose declared type is "Base", instead of "Base*" or "Base&", which will result in the object being converted to type Base.
Bad example:
Derived derived;
Base base = derived;
base.doSomething(); // This is Base's version of doSomething()
Good example:
Base* base = new Derived; // NOTE: declared type is "Base*"
base->doSomething(); // This will call Derived version
delete base;
Side-note: you should use a scoped_ptr, shared_ptr, unique_ptr, or some other smart pointer class instead of using a pointer directly as in my example; however, to not obscure the issue, I have opted to use a raw pointer in this example. For more information about "slicing", see:
What is the slicing problem in C++? - StackOverflow
Slicing in C++
Original solution
You could do something like this:
class Base {
public:
Base() {}
virtual ~Base() {}
virtual void start() {
startInternal();
}
virtual void stop() {
stopInternal();
}
void doSomething() {
startInternal();
// ...
stopInternal();
}
private:
void startInternal() {
// ...
}
void stopInternal() {
// ...
}
};
class Derived : public Base {
public:
Derived() {}
virtual ~Derived() {}
virtual void start() {
// ...
}
virtual void stop() {
// ...
}
};
If you do this, then doSomething() will use the internal version of start/stop which isn't overridden. You will find this pattern a lot, when a constructor/destructor needs to share logic with a virtual method.
Also, not related to the issue at hand, don't forget that you should always create a virtual destructor whenever you create a class that has virtual methods.