In Delphi we have an option to do a thing like this:
TClass1 = class
procedure Test; virtual;
end;
TClass2 = class(TClass1)
procedure Test; override;
end;
So in code, If I create an instance of TClass2, even if I cast the object like:
TClass1(ObjectClass2).Test;
The application will call the function declared on TClass2.
But in C/C++ I could not find a way to do this.
If I declare some void as virtual and implement the same void in the children class when I do the cast to the parent class it'll not use the implementation of the children class.
Does anyone know how I can reproduce the behavior of Delphi in C/C++ ?
New informations:
These are my files.
---------------------- File Filho.hpp
#ifndef FILHO_HPP
#define FILHO_HPP
#include "Pai.hpp"
class Filho : public Pai {
public:
Filho();
virtual ~Filho();
void metodoX();
};
Filho::Filho() {}
Filho::~Filho() {}
void Filho::metodoX() {
std::cout << "Hello Filho!" << std::endl;
}
#endif
---------------------- File Pai.hpp
#ifndef PAI_HPP
#define PAI_HPP
#include <iostream>
class Pai {
public:
Pai();
virtual ~Pai();
virtual void metodoX();
};
Pai::Pai() {}
Pai::~Pai() {}
void Pai::metodoX() {
std::cout << "Hello Pai!" << std::endl;
}
#endif
---------------------- File Main.hpp
#include "Pai.hpp"
#include "Filho.hpp"
int main() {
Pai pai;
pai.metodoX(); //Here output the msg Hello Pai!
Filho filho;
filho.metodoX(); //Here output the msg Hello Filho!
((Pai) filho).metodoX(); //Here output the msg Hello Pai! , but here if I use the directive 'override' in Delphi, the output will be Hello Filho!. Here is my doubt.
return 0;
}
I'm not a Delphi expert, but I can explain how this stuff behaves in C++.
So in C++, you can have a class that defines a virtual function, which means that if you use a base class pointer/reference to an object, that function can be invoked via dynamic dispatch (i.e. runtime function lookup).
#include <iostream>
class BaseClass
{
public:
virtual void virtFunc() { std::cout << "BaseClass\n"; } // notice the 'virtual' keyword
void nonvirtFunc() { std::cout << "BaseClass\n"; }
};
class SubClass : public BaseClass
{
public:
virtual void virtFunc() { std::cout << "SubClass\n"; }
void nonvirtFunc() { std::cout << "SubClass\n"; }
};
int main()
{
// You need to use base class pointers/references
SubClass sc = SubClass();
BaseClass *bcp = ≻
bcp->virtFunc(); // prints "SubClass"
bcp->nonvirtFunc(); // prints "BaseClass"
// doing it by allocating an object on heap
BaseClass *dbcp = new SubClass();
dbcp->virtFunc(); // prints "SubClass"
dbcp->nonvirtFunc(); // prints "BaseClass"
delete dbcp; // in a real program, you should have a virtual destructor which will be called from this code
BaseClass bc = SubClass();
bc.virtFunc(); // prints "BaseClass", and in more complex objects, slicing occurs
}
New Code You Posted
I see that you updated with your code that does this:
((Pai)filho).metodoX();
So when you do that, you are not using pointers/references to a base class. You are just casting the filho object to a Pai object. This does not result in a polymorphic function call, and instead will just call the Pai::metodoX() function.
If you did this instead:
((Pai*)filho)->metodoX();
It would call Filho's metodoX() polymorphically.
In C++ you would write:
class Class1
{
public:
virtual void Test();
};
class Class2: public Class1
{
public:
virtual void Test();
};
Class1* obj = new Class2();
obj->Test();//calls Class2.Test()
This achieves the same as your Delphi example.
The key is to create the C++ object on the heap and maintain a reference to it, which is of course the only way to do things in Delphi which does not support stack based objects.
TClass1* obj = new TClass2 ;
obj->procedure();
If, TClass1 ( base class) and TClass2 ( derived class ) has hierarchial relationships( i.e., inheritance )
class TClass1
{
public:
virtual void procedure(){} // Assuming procedure's return type is void.
virtual ~TClass1(){}
};
class TClass2 : public TClass1
{
public:
void procedure(){}
};
Related
For example, I have 2 classes (in reality, it's more, that's why I'm asking this question) with the same methods:
class class1{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
class class2{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
And now a third one in which I want to deal with the two classes in the same manner:
class upclass{
public:
upclass(class12* argclass){
myclass=argclass;
myclass->init();
}
void domorestuff(){
myclass->dostuff();
}
private:
class12* myclass; //pointer to class 1 OR class 2
};
My question is now, do I need multiple constructors and multiple declarations to make it work or is there a way around it? Is it even possible to make "class12" a spacekeeper for these types without preprocessor-directives?
I am sorry to say, this is a wide field and there are really many many possible solution.
But I guess that we are talking about object- oriented programming, derivation and plymorphic functions. What you describe, will be typically solved with a class hierachy.
You have one base class with virtual (polymorphic) functions.
Then you derive other classes from this base class and override the virtual functions from the base class.
In a 3rd step, you create some instances of the derived classes dynamically, during runtime and you store the newly created classes (their address) in a pointer to the base class.
Later, you can call any of the virtual overriden function through the base class pointer. And mechanism behind the scenes will call the correct function for you.
Additionally. You defined some function init. Such a function name suggests the usage of a class-constructor. This will be called automatically in the correct sequence. First the base class constructor and then the derived class constructor.
Please see the below example:
#include <iostream>
#include <string>
class Base {
std::string baseName{};
public:
Base() { // Do initialization stuff
baseName = "Base";
std::cout << "\nConstructor Base\n";
}
virtual void doStuff() { // virtual function
std::cout << baseName << '\n';
}
};
class Derived1 : public Base {
std::string derivedName{};
public:
Derived1() : Base() { // Do initialization stuff
derivedName = "Derived1";
std::cout << "Constructor Derived1\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
class Derived2 : public Base {
std::string derivedName{};
public:
Derived2() : Base() { // Do initialization stuff
derivedName = "Derived2";
std::cout << "Constructor Derived2\n\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
int main() {
Base* base = new Base();
Base* derived1 = new Derived1(); // Store in base class pointer
Base* derived2 = new Derived2(); // Store in base class pointer
base->doStuff();
derived1->doStuff(); // Magic of polymorphism
derived2->doStuff(); // Magic of polymorphism
}
The Base class pointer will accept all classes derived from Base.
Please note. In reality you ould not use raw pointers and also to the constructor differently. This is just fotr demo.
But, you need to read several books about it to get the complete understanding.
You can explicitly write "store one of these" via std::variant and obtain the actual type (when needed) through std::visit:
#include <variant>
using class12 = std::variant<class1*, class2*>;
class upclass {
public:
upclass(class12 argclass): myclass{argclass} {
visit([](auto classn) { classn->init(); }, myclass);
}
void domorestuff() {
visit([](auto classn) { classn->dostuff(); }, myclass);
}
private:
class12 myclass;
};
If those visits get too repetitive, you might consider writing a pretty API to hide them:
class prettyclass12: public std::variant<class1*, class2*> {
private: // both g++ and clang want variant_size<>, a quick hack:
auto& upcast() { return static_cast<std::variant<class1*, class2*>&>(*this); }
public:
using std::variant<class1*, class2*>::variant;
void init() { visit([](auto classn) { classn->init(); }, upcast()); }
void dostuff() { visit([](auto classn) { classn->dostuff(); }, upcast()); }
};
class prettyupclass {
public:
prettyupclass(prettyclass12 argclass): myclass{argclass} { myclass.init(); }
void domorestuff() { myclass.dostuff(); }
private:
prettyclass12 myclass;
};
I have an abstract class Job and other classes that implement it like:
Waiter and Builder, all of them implement my function in the same way.
For example:
Waiter::changeScore()
{
score += top_score;
}
How may I prevent this kind of code duplication?
Constraints:
I want to keep Job abstract.
Each Waiter or Builder has its own top_score value (It differs between classes and objects of the same class).
Not all member functions of an abstract class need to be pure virtual (as long as at least one is). Your changeScore member is an ideal candidate as a 'real' base class function. Further, not only does it not need to be pure virtual, it doesn't even need to be virtual at all (unless you want your polymorphism to change what a pointer to a derived class will see, for that function).
As each class (or object) will have its own value of top_score (as you have stated), then that (data) member can also be part of the 'abstract' base class.
You can even add a single 'dummy' pure virtual function in your base class (which is never intended to be used, even by a derived class), just to make sure that instances aren't accidentally created. For example, your Job class could have a member:
virtual int Dummy() = 0;
Then, any derived class must have an override for that (however trivial), or the compiler won't allow you to declare an instance of that class. So, your Waiter class would need something like:
int Dummy override { return 1; }
The following code sample may help/demonstrate the idea:
#include <iostream>
#include <memory> // So we can use smart pointers
class Job {
public:
int score{ 0 }, top_score{ 0 };
public:
Job() { }
virtual ~Job() = default;
virtual void Dummy() = 0; // This is sufficient to make the class abstract!
void changeScore() {
score += top_score;
}
virtual void showName() {
std::cout << "Generic Job" << std::endl;
}
};
class Waiter : public Job {
public:
Waiter(int top = 5) { top_score = top; }
~Waiter() override = default;
void Dummy() override { } // We need this in order to use Waiter
void showName() override {
std::cout << "Waiter" << std::endl;
}
};
class Builder : public Job {
public:
Builder(int top = 10) { top_score = top; }
~Builder() override = default;
void Dummy() override { } // We need this in order to use Builder
void showName() override {
std::cout << "Builder" << std::endl;
}
};
int main()
{
Waiter w{ 6 }; // OK - uses explicit value for 'top' parameter
Builder b; // OK - uses default value for 'top' parameter
// Job j; // ERROR - Cannot instantiate abstract class
w.changeScore();
b.changeScore();
std::cout << w.score << std::endl;
std::cout << b.score << std::endl;
// Also, using pointers...
// Job* pj = new Job; // ERROR - Cannot instantiate abstract class
Job* pw = new Waiter; // OK - Now we can make use of polymorphism...
Job* pb = new Builder; // ...with either of these 2 "Job" pointers!
pw->showName();
pb->showName();
delete pw;
delete pb;
// Polymorphism also works with smart pointers (which you SHOULD be using) ...
// std::unique_ptr<Job> upj = std::make_unique<Job>(); // ERROR - Allocating an object of abstract class
std::unique_ptr<Job> upw = std::make_unique<Waiter>(15);
upw->changeScore();
std::cout << upw->score << ": ";
upw->showName();
std::unique_ptr<Job> upb = std::make_unique<Builder>(42);
upb->changeScore();
std::cout << upb->score << ": ";
upb->showName();
return 0;
}
You can define the method in the base class:
Live demo
class Job {
private:
int score;
int top_score;
protected:
//protected constructor to be inherited by derived classes
Job(int top_score) : top_score(top_score) {}
//one pure virtual method is enough to make the class abstract
virtual void some_method() = 0;
public:
void changeScore() { //single method implementation
score += top_score;
}
//to use polymorphism you must use a virtual destructor, unless you use shared_ptr
virtual ~Job(){}
};
class Waiter : public Job {
public:
Waiter(int top_score) : Job(top_score) {}
// pure virtual methods must be overridden in all derived classes
void some_method() override{}
};
class Builder : public Job {
public:
Builder(int top_score) : Job(top_score) {}
void some_method() override{}
};
changeScore() will be implemented in the abstract class and will be usable by all derived classes.
Waiter w(10); //top_score 10
Buider b(20); // top_score 20
b.changeScore();
w.changeScore();
You can make the changeScore method a pure virtual method AND provide an implementation. This would look like this:
class Job {
int score{0};
int top_score{0};
public:
virtual void changeScore() = 0;
};
void Job::changeScore()
{
score += top_score;
}
Then you can call the changeScore method of the Job base class in the child classes like this:
class Waiter : public Job {
public:
virutal void changeScore() override {
Job::changeScore();
}
};
This way if you want to change changeScore, you do not need to change all the implementations in the child classes, but you can just change the implementation in the Job class.
This way you do not need any dummy methods and the Job class remains abstract, while the override in the child classes is trivial and you have a single implementation if you ever want to change it.
EDIT:
If you are wondering where this override keyword comes from, it is introduced in C++11. Since I do not know which C++ version you are using I just wanted to point that out.
You can read about the override specifier here
EDIT II:
Regarding that ever child class has its own top_score, you should set this via the constructor of those child classes.
Like this:
class Job {
protected:
int top_score{0};
Job(top) : top_score(top) {}
...
};
class Waiter : public Job {
public:
Waiter(int top): Job(top) {}
...
};
This way each child class has its own version of top_score
EDIT III:
Putting it all together the classes would look something like this:
class Job {
protected:
int score{0};
int top_score{0};
Job(top) : top_score(top) {}
public:
virtual void changeScore() = 0;
};
void Job::changeScore()
{
score += top_score;
}
class Waiter : public Job {
public:
Waiter(int top): Job(top) {}
virutal void changeScore() override {
Job::changeScore();
}
};
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 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 would to block child classes from overriding a base method and have the child classes override a new method in a parental class. In other words, a child class of the base class blocks the base class methods and delegates to a new method that further child classes must override. I still want the base class method to be available.
Here is an example:
#include <iostream>
#include <string>
struct Base
{
virtual const std::string& class_name(void) = 0;
};
struct Level1
: public Base
{
private: // Prevent child classes from overriding
// the Base::class_name method
const std::string& class_name(void)
{
static std::string name;
name = "class" + class_name_from_level_1();
return name;
}
protected:
// This is the "new" or redirected class that child classes
// must override.
virtual const std::string& class_name_from_level_1(void) = 0;
};
struct Level2
: public Level1
{
static std::string name;
const std::string& class_name_from_level_1(void)
{
if (name.length() == 0)
{
name = "Level2";
}
return name;
}
};
int main(void)
{
Level2 lev2;
std::cout << lev2.class_name() << "\n";
return 0;
}
I am getting the following errors from g++:
$ g++ hiding_virt_methods.cpp -o hiding_virt_methods.exe
hiding_virt_methods.cpp: In function `int main()':
hiding_virt_methods.cpp:15: error: `virtual const std::string& Level1::class_name()' is private
hiding_virt_methods.cpp:43: error: within this context
In the above example, I want the following chain of execution for Level2:
Base::class_name() --> Level1::class_name_from_level_1() --> Level2::class_name_from_level_1()
Also, I only want to block inheritance of specific methods in the Base class. Protected and Private Inheritance affect all the public methods.
So how do I stop the chain of inheritance of specific Base methods at different levels in the inheritance tree?
Edit: Real world example.
I have an interface class Record. Class Record_With_Id inherits from class Record and adds an ID field. The class Record contains an accept_visitor method. Class Record_With_Id overrides accept_visitor to apply to the ID field, then calls a virtual method, record_with_id_accept_visitor, which descendants must implement.
For your immediate problem, you can rename your class_name() functions to class_name_impl() or similar, then in the base class have a class_name() function that calls the implementation one. That way, only the base class version will match when calling class_name() on a derived object.
More generally, you can frustrate attempts to call the base class methods by having same-named functions in the derived classes - as you've done, but anyone can cast to a Base& and call whatever they like. You can't stop virtual methods being overridable in derived classes... you can only frustrate their use.
It's worth remembering that a publicly derived class IS an instance of the base class, and SHOULD provide the base class's interface.
EDIT: re yout "real world example" edit, can you explain the problem with a normal implementation ala...
#include <iostream>
struct Visitor
{
virtual void operator()(int&) const = 0;
};
struct X
{
virtual void visit(Visitor& v) { v(a); v(b); }
int a;
int b;
};
struct X_with_C : X
{
int c;
virtual void visit(Visitor& v) { X::visit(v); v(c); }
};
struct My_Visitor : Visitor
{
void operator()(int& n) const { std::cout << ++n << '\n'; }
};
int main()
{
X x;
x.a = 10;
x.b = 20;
My_Visitor visitor;
x.visit(visitor);
X_with_C xc;
xc.a = -10;
xc.b = -20;
xc.c = -30;
xc.visit(visitor);
X& rx = xc;
rx.visit(visitor);
}
Output:
11
21
-9
-19
-29
-8
-18
-28
hasn't C++11 added final and override?
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Four years later, let me add that C++11 has introduced keyword final:
class Base final {
This can also be applied on the virtual methods:
class Base{
protected:
virtual void doWork() = 0;
public:
virtual void startWork() final { doWork(); }
};
class Derived: public Base{
protected:
virtual void doWork() override { /* some work */ }
public:
// error: overriding final function ‘virtual void Base::startWork()’
virtual void startWork() override { /* something else */ }
};
Visual Studio 2005 and above implement a keyword "sealed", which is a Microsoft extension to C++. You put it in the declaration of Level1::class_name(). I don't think there is a portable way.
It appears that you're trying to do something in a way that's hard.
Depending on what it is that you're trying to achieve, the following may be a solution.
#include <iostream>
#include <string>
struct Base
{
virtual std::string class_name() const = 0;
};
class Level1
: public Base
{
public:
std::string class_description() const
{
return "class " + class_name();
}
};
class Level2
: public Level1
{
public:
virtual std::string class_name() const
{
return "Level2";
}
};
int main()
{
Level2 lev2;
std::cout << lev2.class_description() << "\n";
}
In the above code I've assumed it's for debugging/tracing or something like that. For id purposes look into typeid (a built-in operator).
Cheers & hth.,