I am trying to use a public C++ library and extend it for my purposes. To extend it, I need to change a single virtual method within a single class. The method I am trying to override is part of an inherited class. I posted essentially what I need to do in the code below. I don't really want to rename the function because it is used in a multitude of other places and I don't want to change the source code of the library because it works for some cases, but not mine specifically.
#include <iostream>
class Base {
public:
virtual void getName() = 0;
};
class Dynamic : public Base {
public:
virtual void getName() {
std::cout << "Wrong answer\n";
}
};
//Error in redefinition of class method
void Dynamic::getName() {
std::cout << "Right answer\n";
}
int main()
{
Dynamic mydynam;
mydynam.getName();
}
Here is the code example based on the comments above.
The MyDynamic class is derived from the Dynamic class with the function re-implementation.
It will give you the right answer.
#include <iostream>
class Base {
public:
virtual void getName() = 0;
};
class Dynamic : public Base {
public:
virtual void getName() {
std::cout << "Wrong answer\n";
}
};
////////////////////////
class MyDynamic : public Dynamic {
public:
void getName() {
std::cout << "Right answer\n";
}
};
int main()
{
MyDynamic mydynam;
mydynam.getName();
}
Related
I have a component in a software that can be described by an interface / virtual class.
Which non-virtual subclass is needed is decided by a GUI selection at runtime.
Those subclasses have unique methods, for which is makes no sense to give them a shared interface (e.g. collection of different data types and hardware access).
A minimal code example looks like this:
#include <iostream>
#include <memory>
using namespace std;
// interface base class
class Base
{
public:
virtual void shared()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
// it is not known at compile time, which subtype will be needed. Therefore: pointer has base class type:
shared_ptr<Base> basePtr;
// choose which object subtype is needed by GUI - in this case e.g. now A is required. Could also have been B!
basePtr = make_shared<A>();
// do some stuff which needs interface functionality... so far so good
basePtr->shared();
// now I want to do methodUniqueToA() only if basePtr contains type A object
// this won't compile obviously:
basePtr->methodUniqueToA(); // COMPILE ERROR
// I could check the type using dynamic_pointer_cast, however this ist not very elegant!
if(dynamic_pointer_cast<A>(basePtr))
{
dynamic_pointer_cast<A>(basePtr)->methodUniqueToA();
}
else
if(dynamic_pointer_cast<B>(basePtr))
{
dynamic_pointer_cast<B>(basePtr)->methodUniqueToB();
}
else
{
// throw some exception
}
return 0;
}
Methods methodUniqueTo*() could have different argument lists and return data which is omitted here for clarity.
I suspect that this problem isn't a rare case. E.g. for accessing different hardware by the different subclasses while also needing the polymorphic functionality of their container.
How does one generally do this?
For the sake of completeness: the output (with compiler error fixed):
do A stuff
stuff unique to A
You can have an enum which will represent the derived class. For example this:
#include <iostream>
#include <memory>
using namespace std;
enum class DerivedType
{
NONE = 0,
AType,
BType
};
class Base
{
public:
Base()
{
mType = DerivedType::NONE;
}
virtual ~Base() = default; //You should have a virtual destructor :)
virtual void shared() = 0;
DerivedType GetType() const { return mType; };
protected:
DerivedType mType;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
A()
{
mType = DerivedType::AType;
}
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
B()
{
mType = DerivedType::BType;
}
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
shared_ptr<Base> basePtr;
basePtr = make_shared<B>();
basePtr->shared();
// Here :)
if(basePtr->GetType() == DerivedType::AType)
static_cast<A*>(basePtr.get())->methodUniqueToA();
else if(basePtr->GetType() == DerivedType::BType)
static_cast<B*>(basePtr.get())->methodUniqueToB();
return 0;
}
You can store an enum and initialize it at the constructor. Then have a Getter for that, which will give you the Type. Then a simple static cast after getting the type would do your job!
The goal of using polymorphism for the client is to control different objects with a single way. In other words, the client do not have to pay any attention to the difference of each object. That way, checking the type of each object violates the basic goal.
To achieve the goal, you will have to :
write the concrete method(methodUniqueToX()).
write a wrapper of the concrete method.
name the wrapper method abstract.
make the method public and interface/abstract.
class Base
{
public:
virtual void shared()=0;
virtual void onEvent1()=0;
virtual void onEvent2()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
private:
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
public:
void shared()
{
cout << "do A stuff\n";
}
void onEvent1()
{
this.methodUniqueToA()
}
void onEvent2()
{
}
};
class B : public Base
{
private:
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
public:
void shared()
{
cout << "do B stuff\n";
}
void onEvent1()
{
}
void onEvent2()
{
methodUniqueToB()
}
};
I am expecting "My Game" to print out but I am getting "Base"
This only happens when using methods internally inside the class.
#include <iostream>
namespace Monster { class App {
public:
App(){}
~App(){}
void run(){
this->speak();
}
void speak(){
std::cout << "Base" << "\n";
};
};}; // class / namespace
class MyGame : public Monster::App {
public:
MyGame(){}
~MyGame(){}
void speak(){
std::cout << "My Game" << "\n";
};
};
int main(){
MyGame *child = new MyGame;
child->run();
return 0;
}
In C++ you need to specifically declare a function to be virtual:
class BaseClass {
virtual void speak () {
...
}
};
In C++ a method can only be overridden if it was marked virtual. You can think of virtual as a synonym for "overridable".
The virtual keyword has to appear in the base class. It may also appear optionally in the subclasses at the point of override, but it does not have to.
If you are using a compiler that supports C++11 (and you should if you are learning C++), I recommend that you always use the new override keyword when you mean to override:
class Base {
public:
virtual void speak() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
void speak() override { // <---
std::cout << "Derived";
}
};
If the method isn't actually an override, the compiler will tell you so by giving an error.
It is not always obvious on the first read whether a method is an override. For example the following is correct thanks to return type covariance:
class A {};
class B : public A {};
class Base {
public:
virtual A* foo() {
return nullptr;
}
};
class Derived : public Base {
public:
B* foo() override {
return nullptr;
}
};
This might not be useful very often, but override makes it clear in case someone has to read it.
Also, if you have at least one virtual method in your class, also make its destructor virtual. This will assure that all the destructors will run when needed and things get cleaned up properly:
class App {
public:
App() {}
virtual ~App() {} // <---
void run() {
this->speak();
}
virtual void speak() {
std::cout << "Base\n";
};
};
I am trying to use abstract classes and I met some problems when defining constructors of derived class. I wrote the following code, based on the answer to this question.
#include <string>
#include <iostream>
class ICommand {
private:
ICommand();
public:
const std::string name;
ICommand(const std::string& name) : name(name) { }
virtual void callMe();
virtual void callMe2();
};
class MyCommand : public ICommand {
public:
int x;
MyCommand(const std::string& name) : ICommand(name) { }
MyCommand(const std::string& name, int x) : ICommand(name), x(x) { }
void callMe() {
std::cout << name << "\n";
}
void callMe2() {
std::cout << name << x << "\n";
}
};
void f(std::string name) {
MyCommand A(name);
A.callMe();
}
This compiles without error. However my aim is to build a .so for a R package). In the R installation process, the .so is build without error, with clang++ -shared, but then there is a verification step which produces
unable to load shared object '/path/object.so':
/path/object.so: undefined symbol: _ZTI8ICommand
I've met this kind of problem before, and there are workarounds — not calling Icommand(name) is fairly simple, but I want to understand what is happening there, and, if possible, how to avoid the workaround.
Thanks in advance for your thoughts.
Answer
For the convenience of future readers: the only necessary change here is to replace the definition of virtual functions in the abstract class by
virtual void callMe() = 0;
virtual void callMe2() = 0;
which makes them pure virtual functions. Why this settles the problem totally beats me.
With the:
class MyClass {
private:
MyClass();
};
You are deleting a default constructor. If you want to call a default constructor then (declare or) define or don't define one but don't delete it. Your derived class default constructor will call the base class default constructor:
#include <string>
#include <iostream>
#include <memory>
class ICommand {
public:
std::string name;
ICommand() : name("The name") { std::cout << "Default base class constructor." << std::endl; }
virtual void callMe() = 0;
};
class MyCommand : public ICommand {
public:
MyCommand(){ std::cout << "Default derived class constructor." << std::endl; };
void callMe() override {
std::cout << name << std::endl;
}
};
void f2(const std::string& name) {
std::shared_ptr<ICommand> p = std::make_shared<MyCommand>();
p->callMe();
}
int main(){
f2("asdasd");
}
Part 2:
If you are trying to use the above classes in a polymorphic way then make your ICommand member functions pure virtual:
virtual void callMe() = 0;
virtual void callMe2() = 0;
Modify the void f function to:
void f(const std::string& name) {
std::shared_ptr<ICommand> p = std::make_shared<MyCommand>(name);
p->callMe();
}
Live example on Coliru.
class ICommand {
private:
ICommand() = default;
public:
const std::string name;
ICommand(const std::string& name) : name(name) { }
virtual ~ICommand() = default;
virtual void callMe() = 0;
virtual void callMe2() = 0;
};
Can anybody explain why Driver init() method is unable to print name property overridden in child?
#include <iostream>
#include <string>
class Driver {
public:
std::string name = "Unknown";
void init() {
std::cout << name << std::endl;
}
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
std::string name = "Specific";
};
int main() {
Driver d;
SpecificDriver sd;
// this gives Unknown Unknown =/
d.init();
sd.init();
}
This gives:
Unknown
Unknown
And should be:
Unknown
Specific
Live Demo
You are not doing quite what you think you may be. You are declaring a variable "name" in driver and a variable "name" in SpecificDriver. When you call init() defined in base class driver, that driver can only access its own name field with value "unknown".
Instead you should initialize the "name" variable using a constructor.
Like this:
class Driver {
public:
std::string name;
Driver():name("Unknown"){} //default
Driver(std::string value):name(value){}
void init() {
std::cout << name << std::endl;
}
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
SpecificDriver():Driver("Specific"){}
};
int main() {
Driver d;
SpecificDriver sd;
d.init();
sd.init();
}
Edit: Live Demo http://coliru.stacked-crooked.com/a/c453758867454348
In C++, virtual inheritance is opt-in and not implicit.
When you have this code
class Driver {
public:
std::string name = "Unknown";
void init() {
std::cout << name << std::endl;
}
};
the symbol name will be resolved statically based on what is in scope at that time.
If you later declare a global variable name it has no effect on the meaning of this code. If you later derive from this class Driver, the init function when it is inherited for that class, won't have a different meaning, as in your example.
This "static" dispatch is the default behavior in C++ because it is the simplest and fastest. Especially, it is important that it works this way if you are doing things with templates and inheritance later, otherwise lots of code would have lots of extra overhead.
Alex Zywicki shows one way that you could achieve what you want. Another way would be to use virtual dispatch to get the string. Something like this:
class Driver {
public:
virtual std::string name() const {
return "Unknown";
}
void init() {
std::cout << name() << std::endl;
}
};
class SpecificDriver : public Driver {
virtual std::string name() const override {
return "Specific";
}
};
It is possible to access the class member of the child class through CRTP.
#include <iostream>
template <typename Derived>
class Driver {
public:
void init() {
std::cout << static_cast<Derived*>(this)->name << std::endl;
std::cout << Derived::value << std::endl;
}
};
class SpecificDriver : public Driver<SpecificDriver> {
public:
std::string name = "Specific";
static constexpr char* value = "Another specific string";
};
int main() {
SpecificDriver g;
g.init();
}
If you need a common base class for storing these in, or combining with normal polymorphic behavior you can make the template class Driver inherit from a common base class.
I am expecting "My Game" to print out but I am getting "Base"
This only happens when using methods internally inside the class.
#include <iostream>
namespace Monster { class App {
public:
App(){}
~App(){}
void run(){
this->speak();
}
void speak(){
std::cout << "Base" << "\n";
};
};}; // class / namespace
class MyGame : public Monster::App {
public:
MyGame(){}
~MyGame(){}
void speak(){
std::cout << "My Game" << "\n";
};
};
int main(){
MyGame *child = new MyGame;
child->run();
return 0;
}
In C++ you need to specifically declare a function to be virtual:
class BaseClass {
virtual void speak () {
...
}
};
In C++ a method can only be overridden if it was marked virtual. You can think of virtual as a synonym for "overridable".
The virtual keyword has to appear in the base class. It may also appear optionally in the subclasses at the point of override, but it does not have to.
If you are using a compiler that supports C++11 (and you should if you are learning C++), I recommend that you always use the new override keyword when you mean to override:
class Base {
public:
virtual void speak() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
void speak() override { // <---
std::cout << "Derived";
}
};
If the method isn't actually an override, the compiler will tell you so by giving an error.
It is not always obvious on the first read whether a method is an override. For example the following is correct thanks to return type covariance:
class A {};
class B : public A {};
class Base {
public:
virtual A* foo() {
return nullptr;
}
};
class Derived : public Base {
public:
B* foo() override {
return nullptr;
}
};
This might not be useful very often, but override makes it clear in case someone has to read it.
Also, if you have at least one virtual method in your class, also make its destructor virtual. This will assure that all the destructors will run when needed and things get cleaned up properly:
class App {
public:
App() {}
virtual ~App() {} // <---
void run() {
this->speak();
}
virtual void speak() {
std::cout << "Base\n";
};
};