C++: Calling a Recursive function of an Abstact function - c++

I would like to know how to call a recursive function of an abstract class using C++.
//A.h
class A {
public:
virtual void some() = 0 ;
};
//B.h
#include "A.h"
class B : public A {
public:
void some() ;
};
// B.cpp
void B::some(){
system("pause");
} ;
//C.h
#include "B.h"
class C : public B {
public:
static void callF() ;
};
// C.cpp
void C::callF(){
some();
} ;
I have edited the code. Still not working.

In A and B the function should be either public or protected.

Just use somefunction() inside the body of C::callingF() eg like
void C::callingF()
{
if (somecondition)
somefunction();
}
and you could use ptr->somefunction() if ptr is a pointer to some C or B i.e. a pointer to some A
But please, take hours to read a good book about the C++ programming language. We cannot explain it here in a few minutes. A book explains better...

Related

Predeclare subclasses [duplicate]

I recently got stuck in a situation like this:
class A
{
public:
typedef struct/class {…} B;
…
C::D *someField;
}
class C
{
public:
typedef struct/class {…} D;
…
A::B *someField;
}
Usually you can declare a class name:
class A;
But you can't forward declare a nested type, the following causes compilation error.
class C::D;
Any ideas?
You can't do it, it's a hole in the C++ language. You'll have to un-nest at least one of the nested classes.
class IDontControl
{
class Nested
{
Nested(int i);
};
};
I needed a forward reference like:
class IDontControl::Nested; // But this doesn't work.
My workaround was:
class IDontControl_Nested; // Forward reference to distinct name.
Later when I could use the full definition:
#include <idontcontrol.h>
// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
// Needed to make a forwarding constructor here
IDontControl_Nested(int i) : Nested(i) { }
};
This technique would probably be more trouble than it's worth if there were complicated constructors or other special member functions that weren't inherited smoothly. I could imagine certain template magic reacting badly.
But in my very simple case, it seems to work.
If you really want to avoid #including the nasty header file in your header file, you could do this:
hpp file:
class MyClass
{
public:
template<typename ThrowAway>
void doesStuff();
};
cpp file
#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"
template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
// ...
}
But then:
you will have to specify the embedded type at call time (especially if your function does not take any parameters of the embedded type)
your function can not be virtual (because it is a template)
So, yeah, tradeoffs...
I would not call this an answer, but nonetheless an interesting find:
If you repeat the declaration of your struct in a namespace called C, everything is fine (in gcc at least).
When the class definition of C is found, it seems to silently overwrite the namspace C.
namespace C {
typedef struct {} D;
}
class A
{
public:
typedef struct/class {...} B;
...
C::D *someField;
}
class C
{
public:
typedef struct/class {...} D;
...
A::B *someField;
}
If you have access to change the source code of classes C and D, then you can take out class D separately, and enter a synonym for it in class C:
class CD {
};
class C {
public:
using D = CD;
};
class CD;
This would be a workaround (at least for the problem described in the question -- not for the actual problem, i.e., when not having control over the definition of C):
class C_base {
public:
class D { }; // definition of C::D
// can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
class B { };
C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
// Danger: Do not redeclare class D here!!
// Depending on your compiler flags, you may not even get a warning
// class D { };
A::B *someField;
};
int main() {
A a;
C::D * test = a.someField; // here it can be called C::D
}
This can be done by forward declare the outer class as a namespace.
Sample: We have to use a nested class others::A::Nested in others_a.h, which is out of our control.
others_a.h
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
my_class.h
#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif
class MyClass {
public:
MyClass(int i);
~MyClass();
void print() const;
private:
std::unique_ptr<others::A::Nested> _aNested;
};
my_class.cpp
#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"
MyClass::MyClass(int i) :
_aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
_aNested->print();
}

Multiple definition of same class function depending on multiple type of the same inherited class?

Is it possible to do multiple definition of same class function (polymorphism) depending on multiple type of inherited class:
#include <iostream>
#include <vector>
#include <string.h>
//All base A class
class A{
public:
int e = 0;
virtual int GetE() = 0; //to make A virtual
};
class A_A : public A{
public:
A_A(){e=1;}
virtual int GetE(){return e;}
};
class A_B : public A{
public:
A_B(){e=2;}
virtual int GetE(){return e;}
};
//All base B Class
class B{
public:
virtual void ActionOnA(A_A& a){a.e = 100;}
virtual void ActionOnA(A_B& a){a.e = 200;}
virtual void ActionOnA(A& a){}
};
class B_A : public B{
public:
/*
B_A as the same behavior of B class but B is virtual
*/
};
class B_B : public B{
public:
/*
B_B do different things on A depending on which A object is passed
*/
virtual void ActionOnA(A_A& a){a.e += -100;}
virtual void ActionOnA(A_B& a){a.e += -200;}
virtual void ActionOnA(A& a){}
};
//now I create a custom A_* class
class A_C : public A{
public:
A_C(){e=90;}
virtual int GetE(){return e;}
};
//Since A_C is never handled anywhere, I must create a new B_* to handle it
//I want it have the behavior of B_A in every A class except for A_C
class B_C : public B_A{
public:
virtual void ActionOnA(A_C& a){a.e = 0;}
};
int main(int argc, const char *argv[])
{
std::vector<A*> AllMyA;
A_A Object1;
A_B Object2;
A_C Object3;
AllMyA.push_back(&Object1);
AllMyA.push_back(&Object2);
AllMyA.push_back(&Object3);
B_A test;
for(A* a : AllMyA){
test.ActionOnA(*a);
std::cout << a->GetE() << '\n';
}
/*
Result should be :
100
200
90
Result is :
1
2
90
*/
AllMyA.clear();
A_A Object4;
A_B Object5;
A_C Object6;
AllMyA.push_back(&Object4);
AllMyA.push_back(&Object5);
AllMyA.push_back(&Object6);
B_B test2;
for(A* a : AllMyA){
test2.ActionOnA(*a);
std::cout << a->GetE() << '\n';
}
/*
Result should be :
100
200
0
Result is :
1
2
90
*/
}
This example don't work, it always call ActionOnA(A& a). Can someone explain me how could I make it work knowing the fact I can't do static_cast because I don't know which type of A_* my A ptr is?
Isn't exist a better way of working? Maybe with template?
There is a big difference between the functions ActionOnA and GetE; GetE is a virtual function, thus, the compiler writes down a jump to the corresponding function in the object's virtual function table, which is determined in run-time.
However, when we look at ActionOnA, the compiler need to "know" what function to write down on compile time (it is not virtual!), therefore, it puts the most suitable function overload, which is ActionOnA(A*). The same problem will occur with templates, which are determined at compile time, therefore, it won't choose the overload according to its run-time type.
As ChrisMM wrote, you can try to make dynamic_cast that may fail. But it seems to me that the problem is a bit different:
You want to have a dynamic function in A which makes the valid operation on run-time:
virtual void updateE(bool shouldResetE);
In A_A:
void updateE(bool shouldResetE) final
{
this->E = shouldResetE ? 100 : this->E - 100;
}
Also, a strong recommendation is to use both override and final specifiers, since it helps catching errors in compile time (override will warn when not properly overriding a function, final will warn when trying to override this function on inheriting classes). If A_* are not meant to be inherited from, specify it using final.

how can i convert my class into a namespace

i have a class in c++ that i want to convert to a namespace
i have tried to look around in google but i couldn't find any solution that will make my class a namespace.
how do i do that? its a class that contains 3 functions.
for example:
class c
{
public:
void A();
void B();
void X();
}
i want to be able to use these functions without creating a new object of the class, i want to to be a namespace.
class C that has functions a(),b(),x(), will turn into a namespace.
p.s, i have CLion 2017
ty
It's much easier than you think.
namespace c
{
void A();
void B();
void X();
}
You probably want something like this:
foo.cpp
#include "bar.h"
int main()
{
bar::A();
bar::B();
}
bar.h
namespace bar
{
void A();
void B();
}
bar.cpp
#include "bar.h"
namespace bar
{
void A()
{
...
}
void B()
{
..
}
}
This is a minimal example without header guards for brevity.
You may want to use static functions
class MyClass
{
public:
static void A();
}
You then may call those functions like this :
MyClass::A();

Override Methods in C/C++ like Delphi

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 = &sc;
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(){}
};

Solving cross referencing

I have a problem creating some form of hierarchy with different object types. I have a class which has a member of another class, like this:
class A
{
public:
A(){}
~A(){}
void addB(B* dep){
child = dep;
dep->addOwner(this);
}
void updateChild(){
child->printOwner();
}
void print(){
printf("Printing...");
}
private:
B* child;
};
And this is class B:
class B
{
public:
void addOwner(A* owner){
ownerObject = owner;
}
//ISNT WORKING
void printOwner(){
ownerObject->print();
}
private:
A* ownerObject;
};
Calling a function of "B" out of class "A" works just fine but trying it vice versa gives a compiler error because A is not defined in B. It actually is by using an include and a forward declaration, but I guess its a cross reference problem which the compiler can not solve.
Is there any chance to solve this problem or should I rethink my design?
You say that you already solved your circular dependency problem by using a forward declaration of A instead of including the header where A is defined, so you already know how to avoid circular includes. However, you should be aware of what is possible and what is not with incomplete types (i.e. types that have been forward declared).
In your case, you try to call the member function print on an object that has an incomplete type; the compiler knows nothing about this type excepts that it will be defined at some point, so it does not allow you to do this. The solution is to remove the implementation of the printOwner member function from the B header and put it into an implementation file:
//B.hpp
class A; // forward declaration
class B
{
public:
void addOwner(A* owner);
void printOwner() const; // I think this member function could be const
private:
A* ownerObject;
};
//B.cpp
#include "B.hpp"
#include "A.hpp" // here we "import" the definition of A
void B::addOwner(A * owner)
{
ownerObject = owner;
}
void B::printOwner() const
{
ownerObject->print(); //A is complete now, so we can use its member functions
}
You could possibly do the same thing in the A header.
You can use forward declaration, and define the member functions outside of the class, i.e.
// A.h
class B;
class A { public:
void addB(B* dep); // don't define addB here.
...
};
// B.h
class A;
class B { public:
void addOwner(A* owner); // don't define addOwner here.
...
};
// A.cpp
#include "A.h"
#include "B.h"
void A::addB(B* dep) {
...
}
// B.cpp
// similar.
You probably should rethink your design, since a crcular parent-child relationship is usually a code smell.
But, you can make the compiler happy :
#include <cstdlib>
#include <cstdio>
class A
{
public:
A(){}
~A(){}
void addB(class B* dep);
void updateChild();
void print(){
printf("Printing...");
}
private:
class B* child;
};
class B
{
public:
void addOwner(A* owner){
ownerObject = owner;
}
//ISNT WORKING
void printOwner(){
ownerObject->print();
}
private:
A* ownerObject;
};
void A::addB(class B* dep){
child = dep;
dep->addOwner(this);
}
void A::updateChild(){
child->printOwner();
}
int main()
{
return 0;
}
You should move B::printOwner implementation to .cpp file.