Reading through a text book, I have come away with the impression that overriding virtual functions only works when using a pointer or reference to the object. The book demonstrates the creation of a pointer of the base class type pointed to an object the derived class type, and uses that to demonstrate a virtual function override.
However, I've now come across the following. Not a pointer in sight, and I was expecting that making function1 virtual would not make a difference, but it does. I'm clearly missing something here and would appreciate an explanation as to what it is. Sorry if my explanation isn't clear; also I expect this has been asked before, but was unable to come up with what to search on.
using namespace std;
class ClassA
{
public:
void function1(); // virtual or not?
void function2();
};
class ClassB : public ClassA
{
public:
void function1();
};
int main()
{
ClassA objA;
ClassB objB;
objA.function1();
cout << "\n";
objA.function2();
cout << "\n";
objB.function1();
cout << "\n";
objB.function2(); // Fourth call
cout << "\n";
}
void ClassA::function1() { cout << "ClassA::function1\n"; }
void ClassA::function2()
{
cout << "ClassA::function2\n";
function1(); // For the fourth call ClassA::function1()
// is called if ClassA::function1() is not virtual
// but ClassB:function1() is called if it is. Why?
}
void ClassB::function1() { cout << "ClassB::function1\n"; }
Many thanks for any help.
It's not a virtual function as it is not marked as one. It's simply a public function accessible from a derived class / object. Your code is not exhibiting polymorphic behavior either. That being said none of your functions are virtual nor overriding. Trivial example for polymorphic installation would be:
#include <iostream>
#include <memory>
class ClassA {
public:
virtual void function1() { // now virtual
std::cout << "ClassA::function1\n";
}
};
class ClassB : public ClassA {
public:
void function1() override {
std::cout << "ClassB::function1\n";
}
};
int main() {
std::unique_ptr<ClassA> p = std::make_unique<ClassB>();
p->function1(); // now calls class B function, overrides class A behavior
}
or through references:
int main() {
ClassB objB;
ClassA& ro = objB;
ro.function1(); // now calls class B function, overrides class A behavior
}
There is little benefit in marking functions as virtual and override if you are not utilizing polymorphic behaviour.
Example of virtual without explicit pointers :
class A
{
public:
virtual void f1()
{
cout << "A::f1()" << endl;
}
void f2()
{
f1();
}
};
class B : public A
{
public:
void f1() override
{
cout << "B::f1()" << endl;
}
};
int main()
{
A a;
B b;
a.f2();
b.f2();
}
function1 is not virtual, obj2 calls the classB function1 because it is a clasB object, the compiler first looks at the most-derived type for a function, then the leftmost base (and on through the bases of that base), and then the next base in multiple inheritance situations. If you took a classA * to obj2 and called function1 it would call the classA function1.
Related
I have been watching several videos, and I have come to know how virtual function calls are processed through late binding.
In early binding, for lines like ptr->func(...), the compiler reviews the data type for ptr and looks in the corresponding class for the func(...) definition.
While during late binding for virtual functions, ptr address is accessed, and then the definition is looked up in the corresponding class.
If I am right about the mechanism I have just mentioned, then why does the following code produce an error?
class A{
public:
void func(){
}
};
class B: public A{
public:
virtual void f4(){
cout<<"Cunt"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Also, why does the below code produce the output base instead of the output derived?
class A{
public:
void f4(){
cout<<"base"<<endl;
}
};
class B: public A{
public:
virtual void f4(){
cout<<"derived"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Please help. Am I wrong about the mechanism?
In class A, the function f4 should be defined as virtual too:
class A {
public:
virtual void f4(){
std::cout << "base" << std::endl;
}
};
In your case, f4 is non-virtual function, due to non-virtual inheritance.
One more thing, derived virtual functions should be mark as override, and the virtual is not necessary:
class B : public A {
public:
void f4() override {
std::cout << "derived" << std::endl;
}
};
If you would try to mark f4 in B as override without making it virtual in A first, you would get the compilation error: error: ‘virtual void B::f4()’ marked ‘override’, but does not override- which means that you won't be able to access it using A class pointer.
Side note: read the following post: Why is "using namespace std;" considered bad practice?
In your first example, A does not have a method named f4(), so the call to ptr->f4() is not valid.
In your second example, A::f4() is not marked as virtual, so the call to ptr->f4() does not perform virtual dispatch, and so calls A::f4() rather than B::f4().
The solution to both problems is the same - make f4() be virtual in A, and have B override it, eg:
class A{
public:
virtual void f4() {
cout << "base" << endl;
}
};
class B: public A{
public:
void f4() override {
cout << "derived" << endl;
}
};
int main(){
A* ptr;
B obj;
ptr = &obj;
ptr->f4();
return 0;
}
For example, I have three classes: A, B::A and C::A, only B and C have virtual method print(), like that:
#include <iostream>
using namespace std;
class A {
public:
virtual void print() {
return;
//do nothing
}
static void Func() {
//how to call all virtual functions print() for one class A?
print(); //doesn't work
}
};
class B : public A {
public:
virtual void print() {
cout << "B" << endl;
}
};
class C : public A {
public:
virtual void print() {
cout << "C" << endl;
}
};
int main() {
B b1;
B b2
C c;
A::Func();
return 0;
}
I wan't use print() for all inherited objects (b1, b2, c) by using just class A. How can I do it?
Declare a static class member of A that's a container of pointers to all instances of A or its subclasses. A std::list will be an excellent choice:
class A {
static std::list<A *> all_instances;
public:
// ...
};
In A's constructor, add its this to the list, saving the new list entry's iterator. In A's destructor, remove its list entry from the list.
So now you will have a private container that enumerates all instances of A, or any of its subclasses.
Writing a static class method that invokes each one's print() method becomes trivial, at this point.
Of course, a little bit of additional work is necessary to implement thread safety, if it's an issue here.
Writing the code for A's constructor or destructor will be your homework assignment.
I am looking for a way to create a method that has to be implemented by every subclass. I also want the subclass to call this method on construction.
It should not be possible to call this method again after class construction..
#include <iostream>
class Base {
public:
Base() {init();}
private:
virtual void init() = 0;
};
class DerivedA : public Base {
public:
DerivedA() {}
private:
virtual void init() { std::cout << "Hello, I am A.";}
};
class DerivedB : public Base{
public:
DerivedB() {}
private:
virtual void init() {std::cout << "Hello, I am B.";}
};
int main(){
DerivedA a;
DerivedB b;
return 0;
}
This is an example, but it is not valid, because it calls a pure virtual method in constructor. Of course I can add init() in every subclass-constructor, but then it can be forgotten on new subclasses.
What is the C++ way of doing this?
The C++ way is to not do this. Init functions are bad. Simply use the constructors.
AFAIK, it is very dangerous to call virtual functions in constructors. Here is a simple example. I slightly modified your code to have init method also implemented in Base class :
#include <iostream>
#include <exception>
class Base {
protected:
Base() {init() ; }
virtual void init() {
std::cout << "Init base" << std::endl;
}
public:
void callinit() {
init();
}
};
class DerivedA : public Base {
public:
DerivedA() {}
protected:
virtual void init() { std::cout << "Hello, I am A."<< std::endl;}
};
class DerivedB : public Base{
public:
DerivedB() {}
protected:
virtual void init() {std::cout << "Hello, I am B."<< std::endl;}
};
int main(){
DerivedA a;
DerivedB b;
a.callinit();
b.callinit();
return 0;
}
and the output is :
Init base
Init base
Hello, I am A.
Hello, I am B.
What can we conclude of that :
once the object is constructed, all is fine and when we call init method we normaly get the correct implementation from derived class
but in constructor, the order is :
call Base constructor
call init method from Base object (since derived object in not still constructed)
call DerivedX constructor
So the method is always the one from Base which is definitively not what you expected.
As the other poster said, you should probably stay away from this, but the easiest example would be to make a public, non-virtual interface method on Base called Init() that must be called after the object is constructed. That method can call a pure-virtual "DoInit" method on the derived classes, and track whether or not it has been called yet with an internal flag.
I don't recommend this, but it will work.
class Base
{
public:
void Init()
{
if(!initialized)
{
DoInit();
initialized = true;
}
}
protected:
virtual void DoInit() = 0; // derived classes need to implement this
private:
bool initialized {false};
};
I faced similar problem and could not find a simple solution. I had to make the initialization in a separate class. An object of this class can be passed to Base/Derive constructors, or this class can be a template parameter.
class Initializer {
. . .
}
class Base {
public:
Base(Initializer* initializer) {
// Get members from initializer
}
}
Or:
template<Initializer TInitializer>
class Base<TInitializer> {
public:
Base() {
TInitializer initializer;
// Get members from initializer
}
}
Sorry, I did not write in C++ too long, so I could prevent some syntax errors.
C++11's call_once gets you most of the way, but it has costs.
The class will not be movable nor copyable.
You must add an extra line in every function that requires the initialization.
It does not prevent the method from being called more than once, but that is easy to add.
#include <iostream>
#include <mutex>
struct Base {
Base() {
std::cout << "Base ctor" << std::endl;
}
void sampleFunction1() {
// this line must be at the start of every function that needs the initialization
std::call_once(initedFlag, &Base::v_init, this);
std::cout << "Base::sampleFunction1" << std::endl;
}
void sampleFunction2() {
// this line must be at the start of every function that needs the initialization
std::call_once(initedFlag, &Base::v_init, this);
std::cout << "Base::sampleFunction2" << std::endl;
}
private:
virtual void v_init() = 0;
std::once_flag initedFlag;
};
Notice that the Derived class has nothing special, except that it provides v_init.
struct Derived : Base {
Derived() {
std::cout << "Derived ctor" << std::endl;
}
private:
void v_init() override {
std::cout << "Derived::v_init" << std::endl;
}
};
Demo code
int main(int argc, const char * argv[]) {
Derived d1;
Derived d2;
std::cout << "Calling d1" << std::endl;
d1.sampleFunction1();
d1.sampleFunction2();
std::cout << "Calling d2" << std::endl;
d2.sampleFunction2();
d2.sampleFunction1();
return 0;
}
Output: Notice that v_init will be called which ever sample function is called first and is not called in the ctors.
Base ctor
Derived ctor
Base ctor
Derived ctor
Calling d1
Derived::v_init
Base::sampleFunction1
Base::sampleFunction2
Calling d2
Derived::v_init
Base::sampleFunction2
Base::sampleFunction1
my question is about inheritance and polymorphism in C++.
class Base
{
public:
virtual void f() { cout << "Base::f()" << endl; }
void f(string s) { cout << "Base::f(string)" << endl; }
};
class Derivate1: public Base
{
public:
void f() { cout << "Derivate1::f()" << endl; }
void f(int i) { cout << "Derivate1::f(int)" <<endl; }
};
class Derivate2: public Base
{
public:
void f() { cout << "Derivate2::f()" << endl; }
void f(char c) { cout << "Derivate2::f(char)" << endl; }
};
int _tmain(int argc, _TCHAR* argv[])
{
//with base pointers
Derivate1 d1;
Derivate2 d2;
Base *b1 = &d1;
Base *b2 = &d2;
b1->f(); //output: Derivate1::f() ok.
b1->f("string"); //output: Base::f(string) ok.
b1->f(1); //error !
b2->f(); //output: Derivate2::f() ok.
b2->f("string"); //output: Base::f(string) ok.
b2->f('c'); //error !
//with direct derivate object
d1.f(); //output: Derivate1::f() ok.
d1.f("string"); //error !
d1.f(1); //output: Derivate1::f(int) ok.
d2.f(); //output: Derivate2::f() ok.
d2.f("string"); //error !
d2.f('c'); //output: Derivate2::f(char) ok.
return 0;
}
If i want to use a redefined function in base class which is accessible in derived object, what i have to do? I don't want to use Base::f; in derived classes.
In this case you need to tell C++ that you want to include the base class definition of f in the derived class. This is done with a using statement
class Derivate1: public Base
{
public:
using Base::f;
...
};
class Derivate2: public Base
{
public:
using Base::f;
...
};
This essentially tells the C++ compiler to include both the derived class and parent class definitions of f when doing name lookup. Without this the C++ compiler will essentially stop at the first type in the hierarchy which has a member named f and consider only the overloads declared in that type.
C++ is usually very strict on this type of inheritance, if you'd like a work around you could use this to solve issues like this d1.f(); :
static_cast<Base*>(&d1)->f("string");
if you'd like to make calls like this: b1->f(1); well.. you can't. That's the whole point of polymorphism. You'd have to declare a virtual method in the Base class that has a method named f(int i) so that the compiler can link the Base class method and the Derivate1 class method:
class Base
{
public:
//...
virtual void f(int i) { printf("Base::f(int)"); }
};
Starting from this code:
class Base{
public:
virtual void foo(){....}
};
class Derived{
public:
void foo(){....}
};
If d is a Derived object, can I in some way invoke the foo method defined in the Base class for this object?
Edit: i mean from the outside, such that d.foo() binds to Base::foo()
Specify it explicitly in the call.
#include <iostream>
class Base{
public:
virtual void foo(){
std::cout << "Base" << std::endl;
}
};
class Derived : public Base{
public:
void foo(){
std::cout << "Derived" << std::endl;
}
};
int main()
{
Derived d;
d.Base::foo();
return 0;
}
Just qualify the call (Assuming that Derived actually inherits from Base, which in your code it doesn't):
Derived d;
d.Base::foo();
Now, while this is doable, it is also quite questionable. If the method is virtual, it is meant to be overridden and users should not call a particular override, but the final-overrider, or else they risk breaking class invariants all the way through.
Consider that the implementation of Derived::foo did some extra work needed to hold some invariant, if users call Base::foo that extra work would not be done and the invariant is broken, leaving the object in an invalid state.
To call it from outside code, you can still explicitly qualify the name in the call:
#include <iostream>
#include <vector>
struct base {
virtual void do_something() { std::cout << "Base::do_something();\n"; }
};
struct derived : public base {
virtual void do_something() { std::cout << "derived::do_something();\n"; }
};
int main() {
derived d;
d.base::do_something();
return 0;
}
If you're using a pointer to the object, you'd change that to d->base::do_something();.