Return a function from multiple derived classes - c++

I have a base class and multiple derived classes from it. Each derived class has a constructor that accepts parameters that were initialized in the base class. All of the constructors are different, however they all accept one common parameter, let's call it Name.
Is there a way for me to display every derived class' name in a shorter way than calling them one after another?
Here's an example. Let's say my base class is Father and my derived classes are Brother, Sister, HalfBrother, HalfSister and this is my driver file:
cout << Brother::Brother().getName() << endl
<< Sister::Sister().getNAme() << endl
<< HalfBrother::HalfBrother().getNAme() << endl
<< HalfSister::HalfSister().getName() << endl;
This will return them fine, but is there a simpler way to do this so that I can get all the names from all the derived classes without having to write them one by one?

You can create a static registry of classes, and populate it from constructors of static members that you insert into classes that you would like to register.
In the header:
class Registration {
static vector<string> registered;
public:
static void showRegistered() {
for (int i = 0 ; i != registered.size() ; i++) {
cout << registered[i] << endl;
}
}
Registration(string name) {
registered.push_back(name);
}
};
In the CPP file:
vector<string> Registration::registered;
With this class in hand, you can do this:
In the headers:
class A {
static Registration _registration;
};
class B {
static Registration _registration;
};
class C {
static Registration _registration;
};
In the CPP files:
Registration A::_registration("quick");
Registration B::_registration("brown");
Registration C::_registration("fox");
This last part is key: declarations of the static _registration variables have a side effect - they insert the name into the vector<string> registered of the Registration class, in no specific order. You can now retrieve the names, print them out, or do whatever you want with them. I added a member-function for printing, but obviously you are not limited by it.
Here is a demo on ideone - it prints
quick
brown
fox

Honestly I am not sure if I understand your question. As said in comment, you should make getName() a method in Father.
class Father {
public:
Father(string name) : m_name(name) {
}
string& getName() {
return m_name;
}
private:
string m_name;
};
class Brother : public Father {
public:
Brother(string name) : Father(name) {
}
};
class Sister : public Father {
public:
Sister(string name) : Father(name) {
}
};
So you can have something like:
vector<Father *> fathers;
Brother brother("...");
Sister sister("....");
father.push_back(&brother);
father.push_back(&sister);
for (vector<Father*>::iterator itr = fathers.begin();
itr != fathers.end();
++itr) {
cout << (*itr)->getName() <<endl;
}

Related

Pointer to a Superclass object may serve as pointers to subclass objects. But can't call memeber functions of the subclass. why?

I am enrolled in a C++ course, where i have the following code snippet:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void run()
{
cout << name << ": I'm running" << endl;
}
};
class Dog : public Pet {
public:
Dog(string n) : Pet(n) {};
void make_sound()
{
cout << name << ": Woof! Woof!" << endl;
}
};
class Cat : public Pet {
public:
Cat(string n) : Pet(n) {};
void make_sound()
{
cout << name << ": Meow! Meow!" << endl;
}
};
int main()
{
Pet *a_pet1 = new Cat("Tom");
Pet *a_pet2 = new Dog("Spike");
a_pet1 -> run();
// 'a_pet1 -> make_sound();' is not allowed here!
a_pet2 -> run();
// 'a_pet2 -> make_sound();' is not allowed here!
}
I'm not able to figure out why this is invalid. Please suggest suitable references for this that have ample explanation about why this is happening.
In C++, the types and names of variables at any point is what the compiler permits itself to know.
Each line of code is checked against the types and names of variables in the current scope.
When you have a pointer to a base class, the type of the variable remains pointer to the base class. The actual object it is pointing at could be a derived class, but the variable remains a pointer to the base class.
Pet *a_pet1 = new Cat("Tom");
a_pet1 -> run();
// 'a_pet1 -> make_sound();' is not allowed here!
the type of a_pet1 is Pet*. It may be pointing at an actual Cat object, but that is not information that the type of a_pet1 has.
On the next line, you are using a_pet1. You can only use it in ways that are valid for a Pet pointer on this line. a_pet1->make_sound() is not a valid operation on a Pet pointer, because the Pet type does not have a make_sound method.
You could do this:
Cat *a_pet1 = new Cat("Tom");
a_pet1 -> run();
a_pet1 -> make_sound(); // it now works!
because we changed the type of a_pet1 from Pet* to Cat*. Now the compiler permits itself to know that a_pet1 is a Cat, so calling Cat methods is allowed.
If you don't want to change the type of a_pet1 (which is a reasonable request), that means you want to support make_sound on a Pet, you have to add it to the type Pet:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void make_sound();
void run()
{
cout << name << ": I'm running" << endl;
}
};
now, a_pet1->make_sound() will be allowed. It will attempt to call Pet::make_sound, which is not Dog::make_sound, and as we didn't provide a definition for Pet::make_sound, this will result in an error at link time.
If you want Pet::make_sound to dispatch to its derived methods, you have to tell the compiler this is what you want. C++ will write the dispatch code for you if you use the virtual keyword properly, like this:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
virtual void make_sound() = 0;
void run()
{
cout << name << ": I'm running" << endl;
}
};
here I both made make_sound virtual, and made it pure virtual. Making it virtual means that the compiler adds information to each Pet and Pet derived object so, when it is actually pointing to a derived object type and not a Pet, the caller can find the right derived method.
Pure virtual (the =0) simply tells the compiler that the base class method Pet::make_sound intentionally has no implementation, which also means that nobody is allowed to create a Pet, or a even Pet derived object instance, without providing a make_sound implementation for its actual type.
Finally, note that I mentioned "permits itself to know". The compiler limits what it knows at certain phases of compilation. Your statement that a_pet1 is a Pet* tells the compiler "I don't want you to assume this is a Cat, even though I put a Cat in there". At later stages of compilation, the compiler can remember that fact. Even at runtime, it is sometimes possible to determine the actual type of an object (using RTTI). The forgetting of the type of the object is both intentional and limited.
It turns out that "forced forgetting" is quite useful in a number of software engineering problems.
There are other languages where all method calls to all objects go through a dynamic dispatch system, and you never know if an object can accept a method call except by trying it at runtime. In such a language, calling make_sound on any object whatsoever would compile, and at runtime it would either fail or not depending on if the object actually has a make_sound method. C++ intentionally does not do this. There are ways to gain this capability, but they are relatively esoteric.
In your example a_pet1 and a_pet2 are pointers to objects of the 'Pet' class so your compiler only allows you to access functions that are actually available in that class. The 'Pet' class iteself does not contain a 'make_sound' function in this case. To fix this problem you can define a 'make_sound' function in the base class and mark it as 'virtual'. This will make a function call over a base pointer always invoke the execution of the according function in the inheriting class.
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void run()
{
cout << name << ": I'm running" << endl;
}
virtual void make_sound() {}
};
class Dog : public Pet {
public:
Dog(string n) : Pet(n) {};
void make_sound() override
{
cout << name << ": Woof! Woof!" << endl;
}
};
class Cat : public Pet {
public:
Cat(string n) : Pet(n) {};
void make_sound() override
{
cout << name << ": Meow! Meow!" << endl;
}
};
int main()
{
Pet* a_pet1 = new Cat("Tom");
Pet* a_pet2 = new Dog("Spike");
a_pet1->run();
a_pet1->make_sound();
a_pet2->run();
a_pet2->make_sound();
}

C++ : Access of a child member from a parent class

Assuming I have this class below : (I minimized the program as much as I could and deleted the private members and functions that are not related to the issue ).
class CBookings
{
public:
CBookings() = default;
private:
std::vector<CPerson *>Persons;
};
Where CPerson is a parent class :
class CPerson
{
public:
CPerson() = default;
friend class CBookings;
protected:
std::string Name;
};
and CStudent the child of CPerson :
class CStudent : public CPerson
{
public:
CStudent() = default;
private:
unsigned int MatriculationNr;
};
In my program I did a load function where I extracted all the names and their MatricualionNrs from a file and put them into the vector Persons using this method :
if (Line.compare("<student>") == 0)
{
CStudent *S1 = new CStudent();
S1->load(src); //Load function is missing in class but ignore it
Persons.push_back(S1);
}
Now if I want to make a print() function to print the names and their MatricualionNrs.
How can I have access to the child member in this case ? I know that printing the Name of CPerson will require me to add CBookings as a friend class to CPerson but how about the MatriculationNr ?
void CBookings::print()
{
for (int i = 0 ; i < Persons.size() ; i++)
{
cout << Persons[i]->Name << " " << (...MatriculationNr??.) << endl;
}
Not really giving you access to child member, but this is a more OOP approach.
If the only thing you were trying to do is to print the different types of Person classes, then a more proper way of doing it is to define a virtual print function in Person class, then override print function in each child classes, and call person->print() in your Booking class.
In your Person class:
class CPerson
{
public:
virtual void Print()
{
std::cout << Name << "\n";
}
protected:
std::string Name;
}
In your Student class:
class CStudent
{
public:
void Print()
{
CPerson::Print(); // this will execute the Print() you defined in CPerson
std::cout << MatriculationNr << "\n";
// Or you can also just cout all information from here:
// std::cout << Name << ", " << MatriculationNr << "\n";
}
private:
int MatriculationNr;
}
Then in your Booking class, you just call print() from all Person:
void CBookings::Print()
{
for (int i = 0 ; i < Persons.size() ; i++)
{
Persons[i]->Print();
}
}
By doing this, you also don't need to declare Booking as a friend in Person class.
Edit:
In case you were wondering why you want to do it this way:
The fact you used a vector<Person*> implied that there might be other types of Person included in the vector, such as Staff. If not, then you should have just used vector<Student*> instead.
In the case you might also have Staff in it, then doing something like:
std::cout << Persons[i]->MatriculationNr wouldn't make any sense because of course Staff would not have such member in it. Instead, Staff might have a Salary, or whatever in it.
If you keep using the friend class to access private members, you would also need to check each Person's type, if they are a Student or a Staff, then call different cout function based on that.
This becomes tedious if you have many different children types, and your Booking::Print() just becomes a huge if - else if - else if block. And you have to update Booking every time you either change the members of your Person classes, or add another child class to Person.
By having overridden Print() function in your children classes, you don't need to do anything to Booking::Print(), they would all use the same person->Print() from your Booking class.
You cannot access the members of CStudent unless you have a CStudent* pointer.
If your base class CPerson has at least one virtual method, you can use dynamic_cast to safely get a pointer to the actual child class. If the pointer does not point to the proper child class you'll receive a nullptr.
CStudent* pStudent = dynamic_cast<CStudent*>(Persons[i]);
if (pStudent)
{
cout << pStudent->Name << " " << pStudent->MatriculationNr << endl;
}
Doing things this way can be a bad code smell, because it bypasses the principle that a class should be responsible for its own actions. It can also get cumbersome as the number of child classes grows or the number of exceptional member accesses increases - that can lead to bugs.

cpp access subclass object methods from function that requires superclass object

I have written the following code:
// constructors and derived classes
#include <iostream>
using namespace std;
class Mother
{
public:
int age;
Mother()
{
cout << "Mother: no parameters: \n"
<< this->age << endl;
}
Mother(int a)
{
this->age = a;
}
void sayhello()
{
cout << "hello my name is clair";
}
};
class Daughter : public Mother
{
public:
int age;
Daughter(int a)
{
this->age = a * 2;
};
void sayhello()
{
cout << "hello my name is terry";
}
};
int greet(Mother m)
{
m.sayhello();
}
int main()
{
Daughter kelly(1);
Son bud(2);
greet(kelly);
}
and my question is this:
Since kelly is an instances of a class derived from Mother it makes sense to me that I can pass it into a function that requires an object of type mother ie. greet. My question is this, is it possible to call the sayhello function from within greet such that it will say
it will say "hello my name is terry" instead of "hello my name is clair".
What you're asking for is called "polymorphic behavior" (or "dynamic dispatch") and it is a basic feature of C++. To enable it, you'll need to do a couple of things:
Tag your sayhello() methods with the virtual keyword (i.e. virtual void sayhello() rather than just void sayhello())
Change the greet() method's argument to pass-by-reference or pass-by-pointer, to avoid object-slicing problems (i.e. int greet(const Mother & m) rather than int greet(Mother m))
Once you've done that, the compiler will intelligently choose which sayhello() method to call at run-time, based on the m argument's actual object-type, rather than hard-coding the choice at compile-time based on the type explicitly listed in the greet function's arguments-list.

how to access elements of a derived class through a parent class in c++?

class game_list
{
public:
string name;
float price;
string platform;
string console;
string conditin;
bool is_portable;
};
class catridgeClass:public game_list
{
string N_bits;
bool is_import;
};
game list is dynamically created and a pointer called mainPointer points to that dynamic object. But I am confused on how to access cartridgeClasss elements through the parent class game_list. I already tried mainPointer->N_bits. Seems like it doesnt work that way? Sorry I am just a noob at c++.
To access catridgeClass attributes, you will need a catridgeClass object.
First, you need to correct your class to have public attributes.
class catridgeClass:public game_list
{
public:
string N_bits;
bool is_import;
};
class anotherClass: public game_list
{
public:
string other_member;
};
Than you need to get a catridgeClass object from the caller function:
int main()
{
std::vector<game_list *> games;
games.push_back(new catridgeClass);
games.push_back(new anotherClass);
for(int i=0; i<games.size(); i++)
{
//You will need to get a catridgeClass object to access it's members.
catridgeClass *catridge_ptr = dynamic_cast<catridgeClass *>(games[i]);
//Or to access anotherClass.
anotherClass *another_ptr = dynamic_cast<anotherClass*>(games[i]);
//If the conversion is not possible, dynamic_cast will return a null pointer
if(catridgeClass != NULL)
std::cout << catridge->N_bits << std::endln;
if(anotherClass != NULL)
std::cout << anotherClass->other_member << std::endln;
}
//And of course, you need to avoid a memory leak
for(int i=0; i<games.size(); i++)
delete games[i]
return 0;
}
Keep in mind that it's not a desired design. If you are trying to use polimorphism, is because all that classes share common behaviours. A better approach would be to use interfaces.
Try a virtual method getNBits() = 0; in parent class, and define it in child class.
See: C++ Virtual/Pure Virtual Explained
A parent class has no information about its child class. The only way to do what you want is to either cast like Dory suggested -- which I usually frown upon -- or to create a virtual function in the parent class that the child class redefines.
Why do I frown upon the cast? Most of the time dynamically casting an object to get data from it represents poorly written code. I'm not sure what the rest of your code looks like, but my guess is that there's a better way to write this via shared functionality. For example, let's say what you want to use these items for is displaying string information. In such a case, the best way to write it would be using virtual functions:
class game_list
{
public:
string name;
float price;
string platform;
string console;
string conditin;
bool is_portable;
public virtual void PrintInfo()
{
cout << "name: " << name << ", price: " << price; //etc
}
};
class catridgeClass:public game_list
{
string N_bits;
bool is_import;
public virtual void PrintInfo()
{
game_list::PrintInfo();
cout << ", bits: " << bits << ", is import: " << is_import;
}
};
Now calling mainPointer->PrintInfo() will print the correct information regardless of its underlying type. Much nicer, and it's the "Object-Oriented Way."
try to use dynamic_cast
catridgeClassPtr = dynamic_cast<catridgeClass*>(GameListPtr);
catridgeClassPtr->N_bits;
full info on dynamic_cast:
http://www.cplusplus.com/doc/tutorial/typecasting/

Dynamically creating an instance of a class from a string containing the class name in C++

Lets say I have a base class with 100 children:
class Base {
virtual void feed();
...
};
class Child1 : public Base {
void feed(); //specific procedure for feeding Child1
...
};
...
class Child100 : public Base {
void feed(); //specific procedure for feeding Child100
...
};
At runtime I want to read a file that contains which children to create and feed. Lets say I've read the file and the vector of strings "names" contains the names of the child classes (ie. Child1, Child4, Child99). Now I'm going to iterate through these strings, create an instance of the specific child, and feed it with its specific feeding procedure:
vector<Base *> children;
for (vector<string>::iterator it = names.begin(); it != names.end(); ++it) {
Base * child = convert_string_to_instance(*it)
child->feed()
children.push_back(child);
}
How would I create the function convert_string_to_instance() such that if it takes in the string "Child1" it returns a "new Child1", if the string argument is "Child4" it returns a "new Child4", etc
<class C *> convert_string_to_instance(string inName) {
// magic happens
return new C; // C = inName
// <brute force?>
// if (inName == "Child1")
// return new Child1;
// if (inName == "Child2")
// return new Child2;
// if (inName == "Child3")
// return new Child3;
// </brute force>
}
C++ does not provide a method for dynamic construction of class instances like this. However, you may be able to use code generation to generate the "brute force" code (like you showed above) from a list of classes. Then, #include the generated code in your convert_string_to_instance method.
You can also set up your project build system to rebuild the generated code anytime the list of classes changes.
I asked a question entitled automatic registration of object creator function with a macro that has the following example program that runs:
#include <map>
#include <string>
#include <iostream>
struct Object{ virtual ~Object() {} }; // base type for all objects
struct ObjectFactory {
static Object* create(const std::string& id) { // creates an object from a string
const Creators_t::const_iterator iter = static_creators().find(id);
return iter == static_creators().end() ? 0 : (*iter->second)(); // if found, execute the creator function pointer
}
private:
typedef Object* Creator_t(); // function pointer to create Object
typedef std::map<std::string, Creator_t*> Creators_t; // map from id to creator
static Creators_t& static_creators() { static Creators_t s_creators; return s_creators; } // static instance of map
template<class T = int> struct Register {
static Object* create() { return new T(); };
static Creator_t* init_creator(const std::string& id) { return static_creators()[id] = create; }
static Creator_t* creator;
};
};
#define REGISTER_TYPE(T, STR) template<> ObjectFactory::Creator_t* ObjectFactory::Register<T>::creator = ObjectFactory::Register<T>::init_creator(STR)
namespace A { struct DerivedA : public Object { DerivedA() { std::cout << "A::DerivedA constructor\n"; } }; }
REGISTER_TYPE(A::DerivedA, "A");
namespace B { struct DerivedB : public Object { DerivedB() { std::cout << "B::DerivedB constructor\n"; } }; }
REGISTER_TYPE(B::DerivedB, "Bee");
namespace C { struct DerivedC : public Object { DerivedC() { std::cout << "C::DerivedC constructor\n"; } }; }
REGISTER_TYPE(C::DerivedC, "sea");
namespace D { struct DerivedD : public Object { DerivedD() { std::cout << "D::DerivedD constructor\n"; } }; }
REGISTER_TYPE(D::DerivedD, "DEE");
int main(void)
{
delete ObjectFactory::create("A");
delete ObjectFactory::create("Bee");
delete ObjectFactory::create("sea");
delete ObjectFactory::create("DEE");
return 0;
}
compile and run output is:
> g++ example2.cpp && ./a.out
A::DerivedA constructor
B::DerivedB constructor
C::DerivedC constructor
D::DerivedD constructor
If you have a lot of classes, you'd usually choose a less brute force approach. A trie or hash_map between class names and factory functions is a good approach.
You can use a codegen approach as suggested by Greg to build this factory table, for example doxygen can parse your source code and output a list of all classes in xml format along with inheritance relationships, so you could easily find all classes deriving from a common "interface" base class.
It sounds like you might be using subclasses for things that should be encoded as fields.
Instead of coding the different behaviour in 100 classes, consider building a look-up table with rules/constants/function-pointers that allow you to implement the proper behaviour from one class.
For example, instead of:
class SmallRedSquare : public Shape {...};
class SmallBlueSquare : public Shape {...};
class SmallBlueCircle : public Shape {...};
class SmallRedCircle : public Shape {...};
class BigRedSquare : public Shape {...};
class BigBlueSquare : public Shape {...};
class BigBlueCircle : public Shape {...};
class BigRedCircle : public Shape {...};
try:
struct ShapeInfo
{
std::string type;
Size size;
Color color;
Form form;
};
class Shape
{
public:
Shape(std::string type) : info_(lookupInfoTable(type)) {}
void draw()
{
// Use info_ to draw shape properly.
}
private:
ShapeInfo* lookupInfoTable(std::string type) {info_ = ...;}
ShapeInfo* info_;
static ShapeInfo infoTable_[];
};
const ShapeInfo Shape::infoTable_[] =
{
{"SmallRedSquare", small, red, &drawSquare},
{"SmallBlueSquare", small, blue, &drawSquare},
{"SmallRedCircle", small, red, &drawCircle},
{"SmallBlueCircle", small, blue, &drawCircle},
{"BigRedSquare", big, red, &drawSquare},
{"BigBlueSquare", big, blue, &drawSquare},
{"BigBlueCircle", big, red, &drawCircle},
{"BigRedCircle", big, blue, &drawCircle}
}
int main()
{
Shape s1("SmallRedCircle");
Shape s2("BigBlueSquare");
s1.draw();
s2.draw();
}
This idea might not be applicable to your problem, but I figure it couldn't hurt to present it anyway. :-)
My idea is like the Replace Subclass with Fields refactoring, but I go a bit further.
You can abuse the preprocessor and set up some static class members that register your classes with a factory via a hash_map like Ben describes. If you have visual studio, look at how DECLARE_DYNCREATE is implemented in MFC. I've done something similar to implement a class factory. Non-standard for sure but since C++ does not offer any kind of support for this type of mechanism any solution is probably going be non-standard.
Edit
I said in a comment earlier I was working on documenting a scaled down version of something I had done. The scaled down version is still rather large so I posted it here. If there is enough interest I can copy/paste it on this site. Let me know.
This is the skeleton of a horrible, horrible way to do it:
class Factory {
public:
virtual Base * make() = 0;
};
template<typename T> class TemplateFactory : public Factory {
public:
virtual Base * make() {
return dynamic_cast<Base *>(new T());
}
};
map<string, Factory *> factories;
#define REGISTER(classname) factories[ #classname ] = new TemplateFactory<classname>()
Then call REGISTER(classname); for every relevant derived class of Base, and use factories["classname"]->make() to get a new object of type classname. Obvious flaws with the above code as written include massive potential for memory leaks, and the general awfulness of combining macros and templates.
Behold the mighty Boost.
The one thing you have to do in order to use my solution is to add a new member to all your classes, and that is a static const string that contains the name of the class. There are probably other ways to do it too, but that's what I have right now.
#include <iostream>
#include <vector>
#include <string>
#include <boost/fusion/container/list/cons.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/view/iterator_range.hpp>
using namespace std;
using boost::fusion::cons;
class Base { virtual void feed(){ } };
class Child1 : public Base{
void feed(){ }
public:
static const string name_;
};
const string Child1::name_ = "Child1";
class Child3 : public Base{
void feed(){ }
public:
static const string name_;
};
const string Child3::name_ = "Child3";
//...
class Child100 : public Base{
void feed(){ }
public:
static const string name_;
};
const string Child100::name_ = "Child100";
// This is probably the ugliest part, but I think it's worth it.
typedef cons<Child1, cons<Child3, cons<Child100> > > MyChildClasses;
typedef vector<Base*> Children;
typedef vector<string> Names;
struct CreateObjects{ // a.k.a convert_string_to_instance() in your example.
CreateObjects(Children& children, string name) : children_(&children), name_(name){ }
template <class T>
void operator()(T& cs) const{
if( name_ == cs.name_ ){
cout << "Created " << name_ << " object." << endl;
(*children_).push_back(new T);
}else{
cout << name_ << " does NOT match " << cs.name_ << endl;
}
}
Children* children_;
string name_;
};
int main(int argc, char* argv[]){
MyChildClasses myClasses;
Children children;
Names names;
names.push_back("Child1");
names.push_back("Child100");
names.push_back("Child1");
names.push_back("Child100");
// Extra test.
// string input;
// cout << "Enter a name of a child class" << endl;
// cin >> input;
// names.push_back(input);
using namespace boost::fusion;
using boost::fusion::begin;
using boost::fusion::for_each;
for(Names::iterator namesIt = names.begin(); namesIt != names.end(); ++namesIt){
// You have to know how many types there are in the cons at compile time.
// In this case I have 3; Child1, Child3, and Child100
boost::fusion::iterator_range<
result_of::advance_c<result_of::begin<MyChildClasses>::type, 0>::type,
result_of::advance_c<result_of::begin<MyChildClasses>::type, 3>::type
> it(advance_c<0 >(begin(myClasses)),
advance_c<3>(begin(myClasses)));
for_each(it, CreateObjects(children, *namesIt));
}
cout << children.size() << " objects created." << endl;
return 0;
}