Let's say we have a derived class from an abstract base class. A pointer to the abstract base class is declared in the main and allocated to the derived class through "new". How do you access the member functions of the derived class from a pointer to the base class (not from an object of the derived class)?
Example:
#include <iostream>
using namespace std;
class clsStudent
{
public:
virtual void display() = 0;// {cout<<"Student\n";}
};
class clsInternational : public clsStudent
{
public:
void display(){cout<<"International\n";}
void passportNo(){cout<<"Pass\n";}
};
class local : public clsStudent
{
public:
void display(){cout<<"International\n";}
void icNo(){cout<<"IC\n";}
};
int main()
{
clsStudent * s = new clsInternational;
clsStudent * s2 = new local;
s->display();
s->passportNo(); //This won't work
return 0;
}
Cheeky answer: don't. I mean, if you really need to, the answer to your technical question is the dynamic_cast operation in C++, in order to a conduct a "downcast" (cast from base to derived class).
But stepping back, this is a reasonable use case for a virtual function. Ask yourself, what is the common meaning I want to access?
In this case, we want all students to have an identifying number.
Working source code: http://ideone.com/5E9d5I
class clsStudent
{
public:
virtual void display() = 0;// {cout<<"Student\n";}
virtual void identifyingNumber() = 0;
};
class clsInternational : public clsStudent
{
public:
void display(){cout<<"International\n";}
void identifyingNumber(){cout<<"Pass\n";}
};
class local : public clsStudent
{
public:
void display(){cout<<"Local\n";}
void identifyingNumber(){cout<<"IC\n";}
};
int main()
{
clsStudent * s = new clsInternational;
clsStudent * s2 = new local;
s->display();
s->identifyingNumber();
s2->display();
s2->identifyingNumber();
return 0;
}
Related
TL;DR
I am trying to pass a subclass into a function that expects the subclass's base class and then store a unique pointer of that base class in a vector in a third, completely separate class.
(C++ 11 and higher)
End TL;DR
I have 3 classes total and then my int main().
The base (abstract) class has a constructor and a virtual function.
The base class constructor is implemented, the virtual function is not.
The second class is the subclass to the base class.
It implements its own constructor and calls the base constructor.
The second part of the sub class is the concrete implementation of the virtual base class function.
I then have a third class that has its own constructor.
This third class has a function whose function header contains a reference to the base class.
This same function then tries to pass this reference to the abstract class and then .push_back() the reference into a vector of std::unique_ptr of this abstract class.
(Because I cannot directly have a vector of abstract class instances.)
My issue is that I am currently unable to get a version of this code to compile.
I have been referencing some resources online to try to solve my problem.
pass unique_ptr as an object
https://stackoverflow.com/questions/8114276/how-do-i-pass-a-unique-ptr-argument-to-a-constructor-or-a-function
adding elements of a vector of a base class
https://stackoverflow.com/questions/31410858/adding-elements-to-stdvector-of-an-abstract-class
can't access derived class method from pointer of base class - not entirely relavent, but good knowledge
https://stackoverflow.com/questions/23489554/cant-access-derived-class-method-from-pointer-of-type-base-class
I have created a shortened version of this problem in an example C++ executable that does not compile.
Here is the file:
/*
This script demonstrates my dilemma of trying to pass a subclass object
as a parameter to a function that expects the base class, and then
take that passed in object in the function and add it to a vector of that object
in a completely different class.
*/
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// This is the function I cannot seem to get to work.
// How can I make the function parameter an abstract class?
// The object being passed in is NOT abstract...
bool addController(Baseclass & basecont)
{
// This line here does NOT compile!!
// controllers.push_back(std::make_unique<What goes here?>(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// Add the subclased controllers to the main class
// THESE 2 lines do not compile!!
// mainbro.addController(cont1);
// mainbro.addController(cont2);
//
return 0;
}
I figure that I am doing something very wrong, but I do not feel the process I outlined in itself is impossible. I just think that I am going about the problem wrong.
I have highlighted, in the script, where I am not sure what I should do and where the code breaks.
I may need to take an alternative approach to the problem, I just do not know what alternatives I have available.
I see different way to fix your code, with different meaning.
Store pointers (main has ownership of the objects)
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(&basecont);
}
protected:
std::vector<Baseclass*> controllers;
};
Transfer ownership
class Mainclass
{
public:
void addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
with main:
int main()
{
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
Mainclass mainbro(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
}
Store copies
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(basecont.clone());
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
With
class Baseclass
{
// ...
public:
virtual int addme(int d) = 0;
virtual std::unique_ptr<Baseclass> clone() = 0;
};
class Subclass : Baseclass
{
// ...
public:
std::unique_ptr<Baseclass> clone() override { return std::make_unique<Subclass>(*this); }
};
Whenever you use base pointers or references with virtual methods, always add a virtual destructor:
virtual ~Baseclass() = default;
This prevents undefined behavior when the base pointers get deleted.
Next bit, use public inheritance to allow the compiler to implicitly upcast from unique_ptr<Subclass> to unique_ptr<Baseclass>:
class Subclass : public Baseclass
Your last issue is one of ownership. By having a vector of unique_ptr, you are saying that your class owns all those objects. But by declaring them on the stack in main you are saying that main owns them. Instead, use make_unique in the main routine, and transfer ownership with std::move:
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
...
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
All together:
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
virtual ~Baseclass() = default;
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
return 0;
}
Demo: https://godbolt.org/z/EyQD6S
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// you need to make the function a template, otherwise
// you'll slice the top off the SubClass, and incorrectly
// make a copy of the base class (which you can't do,
// because BaseClass is pure virtual)
template<typename T>
bool addController(T& basecont)
{
// dont push_back new unique_ptrs, emplace_back instead!
controllers.emplace_back(new T(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// It's worth pointing out that these methods will take new copies of
// cont1 and cont2 (we don't want the mainbro instance to delete the
// memory for cont1 and cont2, since they are stack allocated)
mainbro.addController(cont1);
mainbro.addController(cont2);
//
return 0;
}
Consider the following code:
#include <stdio.h>
#include <iostream>
/// Header-file
class Base {
public:
virtual void do_something() const =0;
int GetAttrib () const {return constattribute_;};
static const int constattribute_;
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
};
class DerivedB : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
};
/// CC-file
using namespace std;
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
The intend being that i have some abstract interface (Base) which defines also a variable, which should be present for all derived classes, and is retrievable. All flavours of subclasses should be forced to/able to redefine their specific value for this variable, at best during class declaration (the values are known at the time the class is declared after all).
I want to achieve code, not altering the main()-program so that the output is '12' and not as of now (uncommenting current lines in the code) '00' (Doing so shadows the fields from base class).
I tried to look into the matter, and there are different paths for solutions, many of which however go contrary to my intuition:
1. Some follow the CRTP pattern, which is however impossible if I want to address my subclasses by their base-ptr in main.
2. Other solutions require to virtualize the 'GetAttrib()' function for every derived instance., which is cumbersome, and action of modifying the attribute is masked within a function definition.
3. A third possibility is to remove the static pattern and have the 'constattribute_' field as a regular member, which however forces me to drag it through all constructors as a parameter.
I am quite sure that there must be some smarter way to do this. Any hints are appreciated.
Using CRTP may get you what you want, assuming you don't have to access GetAttr() through Base* and can leave without constattribute_ in Base itself. Just follow the rule that every programming problem can be solved by entering another level of indirection, which I did below:
class Base {
public:
virtual void do_something() const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
If you need GettAttr from top to bottom of the inheritance tree you can modify the above code a bit, but this will cost you making GetAttr virtual (but still one implementation only):
class Base {
public:
virtual void do_something() const = 0;
virtual int GetAttrib () const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
Please note that I don't know how well (or bad) it will behave with deep inheritance tree (ie. when inheriting from DerivedA and/or DerivedB). In this case I would probably remove BaseConstAttr from inheritance tree right below Base and would try to inject it between most derived class and its predecessor or use multiple inheritance.
What you are requesting requires virtual dispatch somewhere, because you don't know the type of the object you are dealing with until runtime. The purpose of virtual dispatch is to solve exactly the problem you are facing.
The simplest solution is what you have given as number 2: make GetAttrib() virtual, and implement it on each derived class where you introduce a shadowing constattribute_.
static variable in base class is single instance hence it will be reflected same in derived class.
You can make same static member variable in derived class with specific different value you want. Now make getter member function of static variable in Base class as virtual and overload it in derived class which returns is static instance value.
I have update your code to work it, please check ..
#include <iostream>
using namespace std;
class Base {
public:
static const int constattribute_;
virtual void do_something() const =0;
virtual int GetAttrib () const {return constattribute_;};
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
class DerivedB : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
You should get desired output.
Note : Remember all member variables and func in derived class are private.
Basically I have a class let's say Parameter that has a get and set variable.
I also have a base class let's say Vehicle that has a method registerParameter(...) that takes a pointer to function member as getter and a pointer to function member as setter. This method is then supposed to write those two pointers into an object of the parameter class and throws this object into a vector.
And last but not least we have a derived class let's say Car and we call registerParameter(...) with the string "color" as parameter name and a getter and setter from this derived class.
Example in code:
Parameter file
#ifndef BASE_H
#define BASE_H
#include "base.h"
class Parameter
{
std::string (Base::*get)();
void (Base::*set)(std::string);
};
#endif
Base file
#ifndef PARAMETER_H
#define PARAMETER_H
#include <vector>
#include "parameter.h"
class Base
{
public:
std::vector<Parameter> list;
void registerNew(std::string (Base::*get)(), void (Base::*set)(std::string))
{
Parameters parameter;
parameter.get = get;
parameter.set = set;
list.push_back(parameter);
}
};
#endif
Derived file
class Derived
{
public:
Derived derived()
{
registerNew(&getColor, &setColor);
}
std::string getColor()
{
return this->color;
}
std::string setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
I've been thinking about this for days now and I really need the solution until friday evening.
You cannot do what are trying:
The types std::string (Base::*)() and std::string (Derived::*)() are very different. std::string (Derived::*)() cannot be auto converted to std::string (Base::*)().
Take the following scenario.
struct Base
{
int foo() { return 10; }
};
struct Derived : Base
{
int bar() { return 20; }
};
int main()
{
Base base;
int (Base::*bf)() = &Base::foo;
(base.*bf)(); // Should be able to call Base:foo(). No problem.
bf = &Derived::bar; // This is a compiler error. However, if this were allowed....
(base.*bf)(); // Call Derived::bar()?? That will be a problem. base is not an
// instance of Derived.
}
Update
You can do something like:
#include <string>
#include <vector>
class Base;
// Create a base class Functor that provides the interface to be used by
// Base.
struct Functor
{
virtual ~Functor() {}
virtual std::string get(Base& base) = 0;
virtual void set(Base& base, std::string) = 0;
};
// Create a class template that implements the Functor interface.
template <typename Derived> struct FunctorTemplate : public Functor
{
// typedefs for get and set functions to be used by this class.
typedef std::string (Derived::*GetFunction)();
typedef void (Derived::*SetFunction)(std::string);
// The constructor that uses the get and set functions of the derived
// class to do itw work.
FunctorTemplate(GetFunction get, SetFunction set) : get_(get), set_(set) {}
virtual ~FunctorTemplate() {}
// Implement the get() function.
virtual std::string get(Base& base)
{
return (reinterpret_cast<Derived&>(base).*get_)();
}
// Implement the set() function.
virtual void set(Base& base, std::string s)
{
(reinterpret_cast<Derived&>(base).*set_)(s);
}
GetFunction get_;
SetFunction set_;
};
class Base
{
public:
std::vector<Functor*> functorList;
void registerFunctor(Functor* functor)
{
functorList.push_back(functor);
}
};
class Derived : public Base
{
public:
Derived()
{
// Register a FunctorTemplate.
registerFunctor(new FunctorTemplate<Derived>(&Derived::getColor,
&Derived::setColor));
}
std::string getColor()
{
return this->color;
}
void setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
Your base class should know the derived class. That sounds complex but the problem has been solved already:
template<typename DERIVED> class Base
{
public:
class Parameter {
std::string (DERIVED::*get)();
void (DERIVED::*set)();
};
private:
std::list<Parameter> list;
// ...
};
class Derived : public Base<Derived> // !!!
{
registerNew(&Derived::getColor, &Derived::setColor);
};
This solution is known as the Curiously Recurring Template Pattern (CRTP).
Here is my hierarchic of classes.
I have declare following abstract interface class, which have just one function:
class IAuthenticator
{
public:
virtual void CreateJson() = 0;
};
After I have created on more class 'UIData' and inherits it from interface class, in this case:
class UIData : public IAuthenticator
{
protected:
UIData() : mWindowHandle(0)
{ /* Constructor do nothing. **/ }
private:
integer mWindowHandle;
public:
void CreateJson()
{
std::cout<<"UIData::CreateJson\n";
}
};
I have one more class which inherits from UIData
class AuthenticateIn : public UIData
{
private:
string mOrigin;
string mLogoURL;
string mUserID;
public:
void CreateJson()
{
std::cout<<"AuthenticateIn::CreateJson\n";
}
};
Question
In my main function I have write code like this.
int main()
{
AuthenticateIn* ai = new AuthenticateIn();
ai->CreateJson();
}
When I call CreateJson() function I see log "AuthenticateIn::CreateJson". I want to find a way to call CreateJson() and it will be called for all base classes.
I know that I can do that calling this->UIData::CreateJson() from AuthenticateIn class CreateJson function, but is there any other way to do that, some automatic way ? Thanks !!
is there any other way to do that, some automatic way
No, there isn't. You have to call the base class's implementation from the derived class. The compiler won't do this automatically since it doesn't know whether you actually want this.
You have to call the base class function in the derived class sort of like this:
void CreateJson() {
UIData::CreateJSon();
}
etc
No, there is no such way. If you want to call virtual function from base class you should do this directly.
You may not be able to force a call to a virtual base class, but you can use indirection to simulate the behaviour.
typedef int integer;
#include <iostream>
#include <string>
using std::string;
using std::cout;
class IAuthenticator
{
public:
virtual void CreateJson() = 0;
};
class UIData : public IAuthenticator
{
protected:
UIData() : mWindowHandle(0)
{ /* Constructor do nothing. **/ }
private:
integer mWindowHandle;
virtual void CreateJsonPrivate() = 0;
public:
void CreateJson()
{
CreateJsonPrivate();
std::cout<<"UIData::CreateJson\n";
}
};
class AuthenticateIn : public UIData
{
private:
string mOrigin;
string mLogoURL;
string mUserID;
virtual void CreateJsonPrivate()
{
std::cout<<"AuthenticateIn::CreateJson\n";
}
};
int main()
{
AuthenticateIn* ai = new AuthenticateIn();
ai->CreateJson();
}
Output:
AuthenticateIn::CreateJson
UIData::CreateJson
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.