As the answers pointed out, this is a dumb mistake I made that has nothing to do with polymorphism or smart pointer. The corrected version is in the accepted answer.
============== Original question ==================
I am trying to make smart pointer work with polymorphism. In the following prototype code, the implementation for pure virtual function Base::print() should be in the memory block of Derived object. DerivedWrap have access to the pointer to the Derived object.
Why can not DerivedWrap::print() access the function implementation?
using namespace std;
class Base
{
public:
virtual void print() = 0;
};
class Derived : public Base
{
public:
Derived(int in) : i(in) {}
void print() {
cout << "int is " << i << endl;
}
private:
int i;
};
class DerivedWrap
{
public:
DerivedWrap() : DerivedWrap(make_unique<Derived>(2)) {}
DerivedWrap(unique_ptr<Base> pBase) : _pBase(move(pBase)) {}
void print()
{
_pBase->print();
}
private:
unique_ptr<Base> _pBase;
};
int main()
{
DerivedWrap pDW1();
pDW1->print(); // error: request for member ‘print’ in ‘pDW1’, which is of non-class type ‘DerivedWrap()’
DerivedWrap pDW2(make_unique<Derived>(2));
pDW2->print(); // error: base operand of ‘->’ has non-pointer type ‘DerivedWrap’
return 0;
}
You have a couple of issues.
This DerivedWrap pDW1(); is a function declaration whose return
type is DerivedWrap. It is not calling its default constructor which you are expecting to. You need simply
DerivedWrap pDW1; // calls the default constructor
// or
// DerivedWrap pDW1{};
Secondly, the pDW1 is simply a DerivedWrap object. Therefore, no need for calling operator->.
You need in short
DerivedWrap pDW1;
pDW1.print();
The same applies to the pDW2. You need
DerivedWrap pDW2(std::make_unique<Derived>(2));
pDW2.print();
Last but not the least, the Base must-have virtual destructor for the defined behaviour. See more:
When to use virtual destructors?
In short, you need
#include <iostream>
#include <memory>
class Base
{
public:
virtual void print() = 0;
virtual ~Base() = default; // provide virtual destructor
};
class Derived /*final*/: public Base
{
public:
// ... other code
void print() override // recommended to override the virtual functions
{
std::cout << "int is " << i << std::endl;
}
private:
int i;
};
class DerivedWrap /* final */
{
public:
// ...other code
void print()
{
_pBase->print();
}
private:
std::unique_ptr<Base> _pBase;
};
int main()
{
DerivedWrap pDW1; // or DerivedWrap pDW1{};
pDW1.print();
DerivedWrap pDW2{ std::make_unique<Derived>(2) };
pDW2.print();
}
As a side note, please do not practice with using namespace std;
You have some typos there, it should be:
int main()
{
DerivedWrap pDW1; // object instantiation, no () needed
pDW1.print(); //no dereferencing required
DerivedWrap pDW2(make_unique<Derived>(2));
pDW2.print(); // again, no dereference required
return 0;
}
One other note, for polymorphic objects you're going to need a virtual destructor in your base class.
This has nothing to do with polymorphism, virtual functions or smart pointers.
You just made two little typographical mistakes:
DerivedWrap pDW1(); declares a function. Remove the ().
-> dereferences pointers, but neither pDW1 nor pDW2 is a function. Use . instead.
Related
using namespace std;
class Foo
{
public:
virtual void foo();
void foo2();
};
class Bar : public Foo
{
public:
void foo();
void foo2();
};
int main()
{
Foo* f = new Foo;
f->foo(); **//1**
f->foo2(); **//2**
return 0;
}
How compiler knows, 1) is dynamic in nature and 2) is static.
How both are internally called.
Collected from here . . .
Non-virtual member functions are resolved statically. That is, the member function is selected statically (at compile-time) based on the type of the pointer (or reference) to the object.
In contrast, virtual member functions are resolved dynamically (at run-time). That is, the member function is selected dynamically (at run-time) based on the type of the object, not the type of the pointer/reference to that object. This is called “dynamic binding.” Most compilers use some variant of the following technique: if the object has one or more virtual functions, the compiler puts a hidden pointer in the object called a “virtual-pointer” or “v-pointer.” This v-pointer points to a global table called the “virtual-table” or “v-table.”
A pure virtual function is a function that must be overridden in a derived class and need not be defined. A virtual function is declared to be “pure” using the curious =0 syntax. For example:
class Base {
public:
void f1(); // not virtual
virtual void f2(); // virtual, not pure
virtual void f3() = 0; // pure virtual
};
Base b; // error: pure virtual f3 not overridden
Here, Base is an abstract class (because it has a pure virtual function), so no objects of class Base can be directly created: Base is (explicitly) meant to be a base class. For example:
class Derived : public Base {
// no f1: fine
// no f2: fine, we inherit Base::f2
void f3();
};
Derived d; // ok: Derived::f3 overrides Base::f3
Example for Virtual or non-Virtual Fenction
#include <iostream>
using namespace std;
class Base {
public:
virtual void NameOf(); // Virtual function.
void InvokingClass(); // Nonvirtual function.
};
// Implement the two functions.
void Base::NameOf() {
cout << "Base::NameOf\n";
}
void Base::InvokingClass() {
cout << "Invoked by Base\n";
}
class Derived : public Base {
public:
void NameOf(); // *Virtual function*.
void InvokingClass(); // *Nonvirtual function.*
};
// Implement the two functions.
void Derived::NameOf() {
cout << "Derived::NameOf\n";
}
void Derived::InvokingClass() {
cout << "Invoked by Derived\n";
}
Main
int main() {
// Declare an object of type Derived.
Derived aDerived;
// Declare two pointers, one of type Derived * and the other
// of type Base *, and initialize them to point to aDerived.
Derived *pDerived = &aDerived;
Base *pBase = &aDerived;
// Call the functions.
pBase->NameOf(); // Call virtual function.
pBase->InvokingClass(); // Call nonvirtual function.
pDerived->NameOf(); // Call virtual function.
pDerived->InvokingClass(); // Call nonvirtual function.
}
In your example both foo() and foo2() will be from the Foo class.
int main()
{
Foo* f = new Foo;
f->foo(); // Foo::foo
f->foo2(); // Foo::foo2
return 0;
}
For you to illustrate the virtual behavior, you need to make an instance of the derived class
int main()
{
Foo* b = new Bar;
b->foo(); // Bar::foo
b->foo2(); // Foo::foo2
static_cast<Bar*>(b)->foo2(); // Bar::foo2
return 0;
}
Notice in the latter case, since b is actually a Bar, it invokes the overriden virtual method foo. But since foo2 isn't declared virtual and b is a Foo, it will invoke Foo::foo2. However, if we cast f to a Bar, it will invoke Bar::foo2
virtual keyword tells compiler for dynamic binding.
To view dynamic binding in action instantiate Foo pointer with Bar object , refer below code.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class Foo
{
public:
virtual void foo(){std::cout<<"Foo foo"<<std::endl;};
void foo2(){std::cout<<"Foo foo2"<<std::endl;};
};
class Bar : public Foo
{
public:
void foo(){std::cout<<"Bar foo"<<std::endl;};
void foo2(){std::cout<<"Bar foo2"<<std::endl;};
};
int main()
{
Foo* f = new Bar;
f->foo();
f->foo2();
return 0;
}
A class which declares or inherits virtual functions has something called a vtable which is used to look up which function to call when you invoke a virtual function. In effect, this table contains pointers to all the virtual functions in the class, something like this (pseudo-code - this may or may not compile):
class Foo {
void foo_impl(){std::cout<<"Foo foo"<<std::endl;}
struct {
void (*foo_ptr)();
} vtable;
public:
Foo(){vtable.foo_ptr = &Foo::foo_impl;}
void foo(){vtable.foo_ptr();}
void foo2(){std::cout<<"Foo foo2"<<std::endl;}
};
class Bar : public Foo {
void foo_impl(){std::cout<<"Bar foo"<<std::endl;}
public:
Bar(){vtable.foo_ptr = &Bar::foo_impl;}
void foo2(){std::cout<<"Bar foo2"<<std::endl;}
};
Thus, when you call a virtual function, the address is first looked up in the vtable, so if you assign a Bar bar; Foo& foo = bar;, then foo.foo() calls Bar's version of foo() instead of Foo's version.
i do not understand why this behavior occurs:
class Base
{
public:
virtual void enablePolymorphism();
};
class Derived : public Base
{
public:
void enablePolymorphism();
};
class Derived2 : public Base
{
public:
void enablePolymorphism();
};
void callMe(Base base)
{
printf("base");
}
void callMe(Derived derived)
{
printf("derived");
}
void callMe(Derived2 derived2)
{
printf("derived2");
}
int main()
{
Base* pointer = new Derived();
Base* pointer2 = new Derived2();
callMe(*pointer);
callMe(*pointer2);
return 0;
}
this is what i actually want my code to do and i want the method callMe() to be outside the classes therefore i cannot use virtual functions, i want at run-time for the program to call callMe(Derived derived) when i do callMe(*pointer) and callMe(Derived2 derived2) when i do callMe(*pointer2) for which the output would be derivedderived2 but that's not what happens, at compile-time pointer and pointer2 are assumed to be of Base class when dereferenced so the callMe(Base base) is called instead and the output is basebase. How do i achieve the output i want? thank you.
void callMe(A);
void callMe(B);
A*ptr;
callMe(*ptr); // guess which of the above is called?
this has nothing to do with polymorphism, but is simple overloading resolution.
Runtime polymorphism applies only to member functions that are marked with the virtual keyword (or that override a virtual member function):
virtual void callMe();
For a non-member function, or a non-virtual member function, the appropriate overload is selected at compile time based on the declared type (not the runtime type) of the argument(s).
The only thing the compiler sees is that the expression *pointer is of type Base& and therefore succeeds into choosing the correct overload callMe(Base) for the function.
In your case, you can use a polymorphic function instead:
#include <memory>
#include <iostream>
class Base {
public:
virtual void callMe() { std::cout << "called base"; }
};
class Derived : public Base {
public:
virtual void callMe() { std::cout << "called derived"; }
};
int main() {
std::unique_ptr<Base> pointer(new Derived());
pointer->callMe();
return 0;
}
And here is the live example.
How can I call a base class method which is overridden by the derived class, from a derived class object?
class Base{
public:
void foo(){cout<<"base";}
};
class Derived:public Base{
public:
void foo(){cout<<"derived";}
}
int main(){
Derived bar;
//call Base::foo() from bar here?
return 0;
}
You can always(*) refer to a base class's function by using a qualified-id:
#include <iostream>
class Base{
public:
void foo(){std::cout<<"base";}
};
class Derived : public Base
{
public:
void foo(){std::cout<<"derived";}
};
int main()
{
Derived bar;
//call Base::foo() from bar here?
bar.Base::foo(); // using a qualified-id
return 0;
}
[Also fixed some typos of the OP.]
(*) Access restrictions still apply, and base classes can be ambiguous.
If Base::foo is not virtual, then Derived::foo does not override Base::foo. Rather, Derived::foo hides Base::foo. The difference can be seen in the following example:
struct Base {
void foo() { std::cout << "Base::foo\n"; }
virtual void bar() { std::cout << "Base::bar\n"; }
};
struct Derived : Base {
void foo() { std::cout << "Derived::foo\n"; }
virtual void bar() { std::cout << "Derived::bar\n"; }
};
int main() {
Derived d;
Base* b = &d;
b->foo(); // calls Base::foo
b->bar(); // calls Derived::bar
}
(Derived::bar is implicitly virtual even if you don't use the virtual keyword, as long as it's signature is compatible to Base::bar.)
A qualified-id is either of the form X :: Y or just :: Y. The part before the :: specifies where we want to look up the identifier Y. In the first form, we look up X, then we look up Y from within X's context. In the second form, we look up Y in the global namespace.
An unqualified-id does not contain a ::, and therefore does not (itself) specify a context where to look up the name.
In an expression b->foo, both b and foo are unqualified-ids. b is looked up in the current context (which in the example above is the main function). We find the local variable Base* b. Because b->foo has the form of a class member access, we look up foo from the context of the type of b (or rather *b). So we look up foo from the context of Base. We will find the member function void foo() declared inside Base, which I'll refer to as Base::foo.
For foo, we're done now, and call Base::foo.
For b->bar, we first find Base::bar, but it is declared virtual. Because it is virtual, we perform a virtual dispatch. This will call the final function overrider in the class hierarchy of the type of the object b points to. Because b points to an object of type Derived, the final overrider is Derived::bar.
When looking up the name foo from Derived's context, we will find Derived::foo. This is why Derived::foo is said to hide Base::foo. Expressions such as d.foo() or, inside a member function of Derived, using simply foo() or this->foo(), will look up from the context of Derived.
When using a qualified-id, we explicitly state the context of where to look up a name. The expression Base::foo states that we want to look up the name foo from the context of Base (it can find functions that Base inherited, for example). Additionally, it disables virtual dispatch.
Therefore, d.Base::foo() will find Base::foo and call it; d.Base::bar() will find Base::bar and call it.
Fun fact: Pure virtual functions can have an implementation. They cannot be called via virtual dispatch, because they need to be overridden. However, you can still call their implementation (if they have one) by using a qualified-id.
#include <iostream>
struct Base {
virtual void foo() = 0;
};
void Base::foo() { std::cout << "look ma, I'm pure virtual!\n"; }
struct Derived : Base {
virtual void foo() { std::cout << "Derived::foo\n"; }
};
int main() {
Derived d;
d.foo(); // calls Derived::foo
d.Base::foo(); // calls Base::foo
}
Note that access-specifiers both of class members and base classes have an influence on whether or not you can use a qualified-id to call a base class's function on an object of a derived type.
For example:
#include <iostream>
struct Base {
public:
void public_fun() { std::cout << "Base::public_fun\n"; }
private:
void private_fun() { std::cout << "Base::private_fun\n"; }
};
struct Public_derived : public Base {
public:
void public_fun() { std::cout << "Public_derived::public_fun\n"; }
void private_fun() { std::cout << "Public_derived::private_fun\n"; }
};
struct Private_derived : private Base {
public:
void public_fun() { std::cout << "Private_derived::public_fun\n"; }
void private_fun() { std::cout << "Private_derived::private_fun\n"; }
};
int main() {
Public_derived p;
p.public_fun(); // allowed, calls Public_derived::public_fun
p.private_fun(); // allowed, calls Public_derived::public_fun
p.Base::public_fun(); // allowed, calls Base::public_fun
p.Base::private_fun(); // NOT allowed, tries to name Base::public_fun
Private_derived r;
r.Base::public_fun(); // NOT allowed, tries to call Base::public_fun
r.Base::private_fun(); // NOT allowed, tries to name Base::private_fun
}
Accessibility is orthogonal to name lookup. So name hiding does not have an influence on it (you can leave out public_fun and private_fun in the derived classes and get the same behaviour and errors for the qualified-id calls).
The error in p.Base::private_fun() is different from the error in r.Base::public_fun() by the way: The first one already fails to refer to the name Base::private_fun (because it's a private name). The second one fails to convert r from Private_derived& to Base& for the this-pointer (essentially). This is why the second one works from within Private_derived or a friend of Private_derived.
First of all Derived should inherit from Base.
class Derived : public Base{
That said
First of you can just not have foo in Derived
class Base{
public:
void foo(){cout<<"base";}
};
class Derived : public Base{
}
int main(){
Derived bar;
bar.foo() // calls Base::foo()
return 0;
}
Second you can make Derived::foo call Base::foo.
class Base{
public:
void foo(){cout<<"base";}
};
class Derived : public Base{
public:
void foo(){ Base::foo(); }
^^^^^^^^^^
}
int main(){
Derived bar;
bar.foo() // calls Base::foo()
return 0;
}
Third you can use qualified id of Base::foo
int main(){
Derived bar;
bar.Base::foo(); // calls Base::foo()
return 0;
}
Consider making foo() virtual in the first place.
class Base {
public:
virtual ~Base() = default;
virtual void foo() { … }
};
class Derived : public Base {
public:
virtual void foo() override { … }
};
However, this does the job:
int main() {
Derived bar;
bar.Base::foo();
return 0;
}
An important [additional] note: you will still have compilation errors if Name Hiding occurs.
In this case, either utilize the using keyword, or use the qualifer. Additionally, see this answer as well.
#include <iostream>
class Base{
public:
void foo(bool bOne, bool bTwo){std::cout<<"base"<<bOne<<bTwo;}
};
class Derived : public Base
{
public:
void foo(bool bOne){std::cout<<"derived"<<bOne;}
};
int main()
{
Derived bar;
//bar.foo(true,true); // error: derived func attempted
bar.foo(true); // no error: derived func
bar.Base::foo(true,true); // no error: base func, qualified
return 0;
}
I have problem with subclassing and using methods.
I create an instance of class B and store it as a pointer to A. But when I use the pointer to call the overloaded method, the output is "A" not "B". Why?
This works in other languages, what am I doing wrong?
#include <iostream>
using namespace std;
class A {
public:
void f() {
cout << "A";
}
};
class B : public A {
public:
void f() {
cout << "B";
}
};
int main() {
A *a = new B();
a->f();
return 0;
}
f() needs to be declared virtual in the base class A:
class A {
public:
virtual void f() {
cout << "A";
}
};
The other languages you already worked with may default to virtual methods, but C++ doesn't (don't pay for what you don't use: virtual methods incur an indirection when calling them which means they are slightly slower than normal method calls).
By adding virtual, binding will be postponed to runtime (called dynamic binding) and which f() function call will be decided on the type of the value.
Because you have not declared function f() as virtual, binding is static (at compilation time) and will use the type of variable (but not value) to determine which f() to call. So in your present code statment a->f(); calls the A class's f() because a is pointer to the A class.
In order to achieve polymorphic behavior, the method of the base class must be virtual.
So in class A you need to change void f() to virtual void f().
The function must be declared virtual to be able to override it:
#include <iostream>
using namespace std;
class A {
public:
virtual void f() {// Here you must define the virtual.
cout << "A";
}
};
class B : public A {
public:
virtual void f() { //Here the "virtual" is optional, but a good practice
cout << "B";
}
};
int main() {
A *a = new B();
a->f();
return 0;
}
You may face this problem when having not a pointers to the base class, but the actual instances of it (not applicable to the example in this question)
In my case, I had a class Token and its subclass Word:
class Token {
public: virtual string toString() { ... }
}
class Word: public Token {
public: string toString() { ... }
}
Storing them in std::map<string, Token> and retrieving from it I expected to call Word::toString() in code like this:
std::map<string, Token> words;
words.insert("test", Word(...));
words["test"].toString();
instead I called Token::toString() every time.
Solution: to use pointers like this std::map<string, Token*> and treat all instances as pointers
(TBH, I hate pointers already)
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();.