I have a little problem with an exercise. I have 2 classes :
The first :
namespace Abstract{
class AbstractClass{
public:
virtual void setName(const std::string & _name) =0;
virtual void print() =0;
void DynamicCastTest(){};
};
}
The second :
class ConcreteClass : public Abstract::AbstractClass{
std::string type;
public:
ConcreteClass();
ConcreteClass(const char* a);
~ConcreteClass();
static Abstract::AbstractClass* CreateConcreteClass(const char* a);
virtual void setName(const std::string & _name);
virtual void print();
};
And the cpp file of the second class :
#include "concreteClass.h"
ConcreteClass::ConcreteClass(){
type = "";
}
ConcreteClass::ConcreteClass(const char* a){
type = a;
}
ConcreteClass::~ConcreteClass(){}
static ConcreteClass* CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
void ConcreteClass::setName(const std::string & _name){
type = _name;
}
void ConcreteClass::print(){
std::cout<<type<<std::endl;
}
But in my main, when i call :
const char* s = "";
Abstract::AbstractClass* a = ConcreteClass::CreateConcreteClass(s);
In the compilation, Visual out me an error LNK2019 :
"public: static class ConcreteClass * __cdecl ConcreteClass::CreateConcreteClass(char const *)" (?CreateConcreteClass#ConcreteClass##SAPAV1#PBD#Z)
on this last line. Why ?
Ah, got it:
static ConcreteClass* CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
is not a declaration of:
ConcreteClass::CreateConcreteClass(s)
I'll leave it to you to figure out what the fix is, as it's a good learning experience, and I'm 100% sure you don't need to practice copy'n'paste - or you could just wait, because I'm sure someone else will post a "fixed" answer soon, simply because they don't care if you learn or not.
Edit: to clarify. You have declared a static member function in the class. And you have defined a static function that is not a member of any class.
You declare CreateConcreateClass as:
static Abstract::AbstractClass* CreateConcreteClass(const char* a);
but then later on we have this, which is a static function but not the one you declared in your class:
static ConcreteClass* CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
the signature has to match your declaration, and so it should be this:
Abstract::AbstractClass* ConcreteClass::CreateConcreteClass(const char* a){
return new ConcreteClass(a);
}
Related
I did a small exemple to try to explain you with my poor english what I want to do :).
I have a main class who is my engine. This is my parent class of several children.
this is the parent class :
#include <string>
#include <iostream>
#include <vector>
template <typename Type>
class A
{
public:
A(std::string const &str)
: m_str(str)
{
}
void run(void) const {
unsigned int i;
for(i = 0; ACTIONS[i].f != nullptr; i++) {
if(m_str == ACTIONS[i].key) {
return ((*(this).*ACTIONS[i].f)(m_str));
}
}
}
protected:
typedef struct s_action {
std::string key;
void (Type::*f)(std::string const &);
} t_action;
static t_action const ACTIONS[];
std::string m_str;
};
class B : public A<B>
{
public:
B(std::string const &str);
protected:
static t_action const ACTIONS[];
void error(std::string const &str);
void success(std::string const &str);
};
I would like to call children method with table pointer of member function in this parent class A::run as you can see above
This code does not compile.
I know it's not possible to have a static variable virtual, but it's
exactly that I need to do have for A::ACTIONS. I absolutely need to initialise B::ACTIONS to A::run works.
In first Is it possible? Have you got a small exemple of this case?
This is the end of my small code :
#include "Class.hpp"
B::t_action const B::ACTIONS[] = {
{"ERROR", &B::error},
{"SUCCESS", &B::success},
{"", nullptr}
};
B::B(std::string const &str)
: A<B>(str)
{
}
void B::error(std::string const &str) {
std::cerr << str << std::endl;
}
void B::success(std::string const &str) {
std::cout << str <<std::endl;
}
And the main:
#include "Class.hpp"
int main() {
B b("SUCCESS");
b.run();
return (0);
}
I didn't try, normally this code should Display SUCCESS on stdout
Thank you for your help
void run(void) const
{
unsigned int i;
for(i = 0; ACTIONS[i].f != nullptr; i++)
if (m_str == ACTIONS[i].key)
return ((*(this).*ACTIONS[i].f)(m_str));
}
There are multiple reasons why this fails to compile. Not one, but several reasons. This entire dispatching mechanism must be completely redesigned.
The first order of business is that this is a
void run(void) const
A const class method.
The method pointer in question is:
void (Type::*f)(std::string const &);
The method pointer is not const, but mutable. From an existing const class method, you can only invoke other const methods. You cannot invoke non-const methods, either directly or indirectly via a method pointer, from a const class methods.
So the first order of business is to change this to
void (Type::*f)(std::string const &) const;
This also means that all your methods, in the child class, error() and success(), must also be const class methods too.
If it's necessary to use this dispatch mechanism with non-const methods, the run() method cannot be a const class method itself. But this is not the only problem here, so I'll continue with the const method, at hand.
return ((*(this).*ACTIONS[i].f)(m_str));
The this here, is a A<Type>. This is a method of that class. That's what this is here.
The method pointer, f is pointer to a method of Type, not A<Type>. Type is a subclass of A<Type>, and you cannot convert a pointer or a reference to a base class to a pointer or a reference to a subclass, any more than you can take a pointer to A, and convert to a pointer to B when B inherits from A. C++ does not work this way.
The solution is simple, and requires only a few small tweaks. This run() should take a reference to const Type &, and invoke the method via the passed-in reference, then a replacement abstract run() method invokes it, passing *this as a parameter:
public:
virtual void run()=0;
protected:
void run_me(const Type &me) const
{
unsigned int i;
for(i = 0; ACTIONS[i].f != nullptr; i++)
if (m_str == ACTIONS[i].key)
return ((me.*ACTIONS[i].f)(m_str));
}
Then, each subclass that inherits this template only needs to implement a simple facade:
class B : public A<B>
{
public:
void run() const override
{
run_me(*this);
}
EDIT: This addresses the compilation error, but additional work is needed to deal with the fact that static class members cannot be overridden. The solution is also pretty simple: also leverage virtual class methods in order to implement this.
Remove the declaration of ACTIONS from the template base class, and replace it with an abstract function:
virtual const t_action *get_actions() const=0;
And use it in run_me():
const t_action *ACTIONS=this->get_actions();
The rest of run_me() remains as is, and then implement get_actions() in the child class:
const t_action *get_actions() const override
{
return ACTIONS;
}
Pretty much everything else remains the same.
The problem is that A will always use is own defined set of actions, not B's.
You don't need to create A at all, as you want to use B methods and list of methods.
Let's say that you create first a run call function:
template<typename T>
void run(T* obj, const std::string method)
{
const auto& available_methods = obj->get_methods();
auto iter = available_methods.find(method);
if(iter == available_methods.end())
{
// Handle this case
}
std::invoke(iter->second, obj); //C++17, or (obj->*(iter->second))();
}
Now for the class B, you need something very simple:
class B
{
public:
typedef std::unordered_map<std::string, void(B::*)()> MethodMap;
void foo();
static MethodMap& get_methods()
{
static MethodMap map{{"foo", &B::foo}};
return map;
}
};
Populate the map with get_methods() in the static function, and then call run through:
int main()
{
B b;
run(&b, "foo");
}
If you are going to use CRTP, IMO you need to google for CRTP first.
By the way here's a quick direct ans 2 your q:
template<typename crtp_child>
class crtp_base{
using crtp_target=crtp_child;
auto crtp_this(){
return static_cast<crtp_target*>(this);
};
auto crtp_this() const {
return static_cast<crtp_target const*>(this);
};
public:
void run(){
auto range=crtp_this()->actions.equal_range(m_str);
for(auto entry:range)
(crtp_this()->*(entry.second))(m_str);
};
protected:
crtp_base(std::string str):
m_str(str)
{};
std::string m_str;
//...
};
struct crtp_user:
crtp_base<crtp_user>
{
using crtp_base::crtp_base;//ctor fwding
protected:
friend class crtp_base<crtp_user>;
std::unordered_multimap<std::string, void (crtp_user::*)(std::string)> actions;
//...
};
Having trouble with inheritance. I do not know what is wrong with the script..
in main
int main(){
Repository repo("dogs.txt");
FileAdoptionList* a = new CSVDoglist{}; / here is the error
Controller ctrl(repo, dogValidator{}, a);
UI ui(ctrl);
ui.startUI();
delete a;
}
CSVDoglist.h
class CSVDoglist : public FileAdoptionList
{
public:
void writeToFile();
void displayAdoptionlist() const;
};
FileAdoptionList.h
class FileAdoptionList : public AdoptionList
{
protected:
std::string filename;
public:
FileAdoptionList();
virtual ~FileAdoptionList() {}
void setFilename(const std::string& filename);
virtual void writeToFile() = 0;
virtual void displayAdoptionList() const = 0;
};
AdoptionList.h
class AdoptionList
{
protected:
std::vector<Dog> storage;
public:
AdoptionList();
// Adds a dog to the playlist.
void add(const Dog& dog);
// Checks if the adoptionlist is empty.
bool isEmpty();
virtual ~AdoptionList() {}
};
ERRORS:
object of abstract class type "CSVDoglist" is not allowed:
'CSVDoglist': cannot instantiate abstract class Adoptig Dogs
I have read more topics about this problem but I didn't found the solution.
Can someone help me? Thanks
It seems you have a typo.
A function named displayAdoptionlist (contains small l) is declared in CSVDoglist, but the pure virtual function displayAdoptionList (contains large L) isn't overrided in CSVDoglist.
This is Parent Class Foo, and It is abstract(virtual).
And Foo class' methods are declared in Foo.cpp.
[Foo.h]
class Foo
{
public:
Foo();
~Foo();
virtual void methodA(int no, const char* path) = 0;
virtual void methodB(const char* name, const char* path) = 0;
virtual void methodC(const char* name, const char* path) = 0;
// ... more 20 virtual methods
}
[Foo.cpp]
Foo::Foo(){}
Foo::~Foo(){}
Foo::methodA(int no, const char* path)
{
// do something
}
Foo::methodB(const char* name, const char* path)
{
// do something
}
Foo::methodC(const char* name, const char* path)
{
// do something
}
// ... more 20 methods
In Foo class, methodA must be called with parameter no.
And Also parameter no must increase sequentially from 0.
It is very uncomfortable. So I want to override methodA in child class Bar.
Bar class has a memeber variable m_no and methodA without parameter no.
And m_no will increase when methodA called.
This is my code.
[Bar.h]
class Bar : public Foo
{
public:
Bar();
~Bar();
void methodA(const char* path);
private:
int m_no;
}
[Bar.cpp]
Bar::Bar() : m_no(0) {}
Bar::~Bar() {};
Bar::methodA(const char* path)
{
Foo::methodA(m_no++, path);
}
But class Bar is abstract(virtual), because class Bar isn't declare virtual methods (methodA, methodB, methodC and 20 methods more).
So, I edited.
[Bar.h]
class Bar : public Foo
{
public:
Bar();
~Bar();
void methodA(const char* path);
void methodB(const char* name, const char* path);
void methodC(const char* name, const char* path);
// ... more 20 methods
private:
int m_no;
}
[Bar.cpp]
Bar::Bar() : m_no(0) {}
Bar::~Bar() {};
Bar::methodA(const char* path)
{
methodA(m_no++, path);
}
Bar::methodA(int no, const char* path)
{
Foo::methodA(no, path);
}
Bar::methodB(const char* name, const char* path)
{
Foo::methodB(name, path);
}
Bar::methodC(const char* name, const char* path)
{
Foo::methodC(name, path);
}
// ... more 20 methods
How can I inherit class Foo without declare all virtual methods?
How can I inherit class Foo without declare all virtual methods?
You provide an implementation for them.
(note: this part adds to #TommyA's answer, but it is too long for a comment; see second part, for a different approach)
consider:
class Foo
{
public:
Foo();
virtual ~Foo() = 0; // this is the only pure virtual function
virtual void methodA(int no, const char* path);
virtual void methodB(const char* name, const char* path);
virtual void methodC(const char* name, const char* path);
// ... more 20 virtual methods
}
Foo.cpp:
Foo::~Foo() = default; // unless you need to add some impleemntation
// other methods implemented like you did
Bar:
class Bar : public Foo
{
public:
Bar();
virtual ~Bar();
void methodA(const char* path);
// do not implement anything of Foo here (it is inherited already)
private:
int m_no;
}
Second part
Another approach would be to follow the open-closed principle (decide that if the method must be called with an ever increasing number, then it is the responsibility of Foo to implement that, and add a template method implementation):
class Foo
{
public:
// public interface for methodA, accessible to clients
void methodA(const char* path);
protected:
virtual void methodA_impl(int no, const char* path) = 0;
private:
int m_no; // private: not accesible to specializations
};
void Foo::methodA(const char* path)
{
methodA_impl(m_no++, path);
}
class Bar: public Foo
{
// ...
protected:
void methodA_impl(int no, const char* path) override;
}
void Bar::methodA_impl(int no, const char* path)
{
// Bar-speciffic implementation here
}
This follows the open-closed principle because the "number must be incremented at every call" requirement is fixed and cannot be overriden by
specializations.
Clients of Foo specializations cannot change how methodA_impl is called (it is always called correctly) and you have the virtual method behavior you need.
When a base class is pure virtual the child class that you wish to instantiate needs to fully implement the pure virtual methods before you can instantiate it. But you could make a "middle" layer that default implemented the methods, that you then inherited from.
Note: Remember to use virtual destructors creating non-final classes.
The whole point of that class Foo is that has been defined so all derived classes must override all the pure virtual methods.
The most obvious workaround is to complain bitterly to whoever provided class Foo and get them to provide a sensibly designed base class. It is absolutely lousy design to define a class that way, unless it is obvious that ALL virtual functions MUST be overridden. It is also lousy design (because there are circumstances where the result is undefined behaviour) to have a base class that does not have a virtual destructor.
If this is your design, redesign your entire class hierarchy. Seriously, the design is that bad.
However, it is possible to simply derive another class from Foo and override all member functions necessary. For example;
class FooIntermediary : public Foo
{
virtual void methodA(int no, const char* path);
virtual void methodB(const char* name, const char* path);
virtual void methodC(const char* name, const char* path);
};
void FooIntermediary::methodA(int no, const char *path)
{
Foo::methodA(no, path);
}
void FooIntermediary::methodB(const char *name, const char *path)
{
Foo::methodB(name, path);
}
// etc
Then any classes derived from FooIntermediary will only be forced to override any inherited functions from Foo that FooIntermediary has not overridden.
You could find another class, derived from Foo, that can be instantiated, and has (apart from the particular change you seek) all the behaviour your need. By definition, that class will have overridden all of the inherited abstract functions. So derive a class from it, and override only the virtual function you need to.
I have an existing project with the following class inheritance
class Base
{
public:
Base();
virtual ~Base();
void SetID(unsigned short);
virtual inline unsigned short GetID();
protected:
unsigned short id;
};
class Generic : public Base {
public:
Generic(const char *in_name);
const char* GetName() { return name; }
protected:
char name[30];
};
class Actor : public Generic
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
};
Now i created a separate project were i want to provide an interface that has to be implemented in order to use the functionality - i plan on reusing this project for other implementation.
class MyInterface
{
public:
virtual ~MyInterface() {}
// Our methods that need to implemented
virtual const char* GetName() = 0;
virtual void DoSomething(const char* str) = 0;
virtual unsigned short GetID() = 0;
};
Now i simply wanted to use this with my actor class e.g.
class Actor : public Generic, public MyInterface
however it fails to compile
'const char *MyInterface::GetName(void)' : is abstract see declaration of 'MyInterface::GetName'
'unsigned short MyInterface::GetID(void)' : is abstract see declaration of 'MyInterface::GetID'
error C2385: ambiguous access of 'GetName'
could be the 'GetName' in base 'Generic'
or could be the 'GetName' in base 'MyInterface'
The problem is probably that GetName is already implemented in Generic, and GetID is already implemented in Base - so in the child class Actor implementing the Interface is not possible because the compiler is not smart enough to realize there is already an implementation of these methods.
However, i found a workaround - but for this i would have to extend the header of the actor class which is not a nice thing - and i wanted to know if there is another approach - my fix is
class Actor : public Generic, public MyInterface
{
public:
Actor(const char *in_name);
~Actor();
void DoSomething(const char* str);
const char* GetName() { return Generic::GetName(); };
inline unsigned short GetID() { return Base::GetID(); };
};
Now this obviously will not work for varargs methods and i would have to implement existing methods and delegate to the parent again - is there a better solution?
EDIT For clarifications - the classes base,generic and actor exist in another project managed by others, modifications to these should be very limited. - I created a seperate project which creates a static LIB - to use functions of these in conjunction with the actor class - i created an interface to not have any dependency in my own project and also provide a reusable lib for other projects which would simply just need to implement this interface.
class Base
{
protected:
unsigned short id;
public:
void SetID(unsigned short);
virtual inline unsigned short GetID() { return id; }
virtual ~Base() {}
Base(): id() {}
};
class Generic
: public Base
{
protected:
char name[30];
public:
const char* GetName() { return name; }
Generic(const char* in_name): name() {}
};
class Actor
: public Generic
{
public:
void DoSomething(const char* str) {}
~Actor() {}
Actor(const char* in_name)
: Generic( name )
{}
};
class MyInterface
{
public:
// Our methods that need to implemented
virtual const char* name() const = 0;
virtual int id() const = 0;
virtual void doSomething( const char* str ) = 0;
virtual ~MyInterface() {}
};
template< class TpBase >
class MyInterfaceOn
: public virtual MyInterface
, public TpBase
{
public:
typedef TpBase Base;
private:
MyInterfaceOn& mutableSelf() const
{ return *const_cast<MyInterfaceOn*>( this ); }
public:
const char* name() const { return mutableSelf().Base::GetName(); }
int id() const { return mutableSelf().Base::GetID(); }
void doSomething(const char* str) { Base::DoSomething( str ); }
MyInterfaceOn( char const name[] )
: Base( name )
{}
};
class MyActor
: public MyInterfaceOn< Actor >
{
public:
MyActor( char const name[] )
: MyInterfaceOn< Actor >( name )
{}
};
int main()
{
MyInterface const& actor = MyActor( "NN" );
}
I think I messed up somehow in my design because I want to keep a vector of various object types. These types all share a common base class. Example:
Class Buick: AmericanCar
{
}
Class Ford: AmericanCar
{
}
then I did:
vector<AmericanCar*> cars_i_own;
Now, I have my vector of pointers but I don't have the derived class which is what I need. I thought about adding a GetType/SetType function to the base class and then use a dynamic cast. This is clunky though. Did i use the wrong design for this?
Well, what are you trying to do with it? Get the name or cost? You would have something like:
class Car
{
public:
virtual ~Car(void) {}
virtual std::string location(void) const = 0;
virtual std::string name(void) const = 0;
virtual double cost(void) const = 0;
}
class AmericanCar
{
public:
virtual ~AmericanCar(void) {}
virtual std::string location(void) const
{
return "America";
}
}
class Buick : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Buick";
}
virtual double cost(void) const
{
return /* ... */;
}
}
class Ford : public AmericanCar
{
public:
virtual std::string name(void) const
{
return "Ford";
}
virtual double cost(void) const
{
return /* ... */;
}
}
Now you can call these methods polymorphically.
This is somewhat strange, though. You don't need a different class to store names and cost like this:
class Car
{
public:
Car(const std::string& pLocation,
const std::string& pName,
double pCost) :
mLocation(pLocation),
mName(pName),
mCost(pCost)
{
}
const std::string& location(void) const
{
return mLocation;
}
void location(const std::string& pLocation)
{
mLocation = pLocation;
}
const std::string& name(void) const
{
return mName;
}
void name(const std::string& pName)
{
mName = pName;
}
const double cost(void) const
{
return mCost;
}
void cost(double pCost)
{
mCost = pCost;
}
private:
std::string mLocation;
std::string mName;
double mCost;
}
// make cars
std::vector<Car> cars;
cars.push_back(Car("America", "Buick", /* ... */));
The purpose of inheritance / polymorphism is so you don't need to care which derived type you are dealing with.
In particular I think storing data, such as make of car, country of origin etc, encoded in a class hierarchy doesn't seem to be particularly beneficial. Does an AmericanCar do something fundamentally different from, say, a Japanese car (other than consuming more fuel, which again can be better stored in a data member)?
Why do you need to know the derived class? Normally you would have virtual functions to take care of any behavior differences between the two derived classes.
The goal is that the code using the parent class shouldn't have to know the exact class it's working with.
You can use typeid to determine the derived class:
struct Base
{
virtual ~Base() {}
};
struct Derived : public Base { };
int main()
{
Base* b = new Derived();
std::cout << typeid(*b).name() << std::endl;
}
This outputs: "Derived".
But, usually with polymorphism the point is that you shouldn't be concerned with this. You simply call a base-class member function and the proper derived-class member function is called at runtime.