Personalised name in constructor for different subclasses - c++

Instead of "Car" is there a way to set the name variable of each object according to its class, for example "Turbo 01" or "Tank 02" or "Buggy 03", where id contains the amount of vehicles created.
#include <iostream>
#include <string>
#include <sstream>
static int id = 0; //Total Number of cars right now
class Car
{
private:
std::string name;
Car()
{
std::ostringstream tmp;
std::string temp;
tmp << "Car" << ++id;
temp = tmp.str();
}
Car(std::string name){this->name=name; id++;}
};
class Turbo : public Car()
{
Turbo():Car()
{
}
Turbo(std::string name):Car(name);
{
}
};

First, let's make sure that the class Car compiles by providing the two required template arguments std::array : type and size. For example: std::array<int, 10>.
The problem is that Turbo needs a valid constructor for its base type Car before it can do anythin else. There are two ways, for it to work:
Either you design Car so that there is a default consructor (i.e.without parameters)
Or you put the constructor for Car in the initialisezer list of the Turbo.
For your edited question, the problem is that the Car constructor must be visible for the derived class, so either public or protected, but not private. You can also use default parameters to get rid of redundant code.
Here a solution:
class Car
{
private:
static int id; //Total Number of cars right now SO MEK IT a static class member
std::string name;
public: // public or protected so that derived classes can access it
Car(std::string n="Car") // if a name is provided, it will be used, otherwhise it's "Car".
{
std::ostringstream tmp;
std::string temp;
tmp << n << ++id;
name = tmp.str(); // !! corrected
}
};
int Car::id = 0; // initialisation of static class member
class Turbo : public Car
{
public: // !! corrected
Turbo(std::string n="Turbo") :Car(n) // !!
{ }
};

Related

How to create objects that has a variable based on the data from another object that is passed in the constructor

The title may be a little confusing but hear me out. I have this two classes , Entity and Human.
Entity is the parent class of human. When I create a human object, it will require an Entity object passed as argument in the constructor so all the human objects that I create has the same Entity object info.
This is my problem: If I change some data from the Entity object I want to update all the data from the Human objects that I created using that Entity Object in the constructor.
I want to implement this in ones of my University projects so I am allowed to use only the standard library.
I wrote this example so it's easier to understand:
#include <iostream>
using namespace std;
class Entity{
private:
//DATA
int life;
public:
//DEFAULT CONSTRUCTOR
Entity() {life = 100;}
//PARAMETRIZED CONSTRUCTOR
Entity(int life) {this -> life = life;}
//GETTER
int get_life(){return life;}
//SETTER
void set_life(int new_life){life = new_life;}
//FUNCTIONS
void print_life() {cout << "This entity has " << life << " life" << endl;}
};
class Human : public Entity{
public:
//DATA
string name;
//DEFAULT CONSTRUCTOR
Human() {name = "N/A";}
//PARAMETRIZED CONSTRUCTOR
Human(string name, Entity object){
Entity::set_life(object.get_life());
this -> name = name;
}
};
int main(){
//DATA
Entity Human_data(50);
Human Hero("Steve", Human_data);
Human Villain("Mike", Human_data);
//BODY
Human_data.set_life(5000);
Hero.print_life();
//END MAIN
return 0;}
As you can see, after I update Human data life from 50 to 5000, it does not also change Hero and Villain life to 5000 and only changes Human data life to 5000.
I'm assuming that when you call Human_data.set_life(5000) you want to effect all Human objects constructed with the Human_data object.
Here's an example of how you might use references for that. But note putting a reference inside a class is not without consequences. You might use a pointer instead, or even better a smart pointer. But I'm just trying to indicate the general idea.
On a technical note, using references means you have to get used to using initializer lists since references cannot be assigned.
#include <iostream>
using namespace std;
class Entity{
private:
int life;
public:
Entity() : life(100) {}
Entity(int life) : life(life) {}
int get_life() {return life;}
void set_life(int new_life){life = new_life;}
void print_life() {cout << "This entity has " << life << " life" << endl;}
};
class Human { // no inheritence
private:
Entity& entity; // store a reference to the entity
public:
string name;
Human(string name, Entity& object) // object is a reference
: entity(object), name(name)
{
}
void print_life() { entity.print_life(); } // forward to entity
};
int main(){
//DATA
Entity Human_data(50);
Human Hero("Steve", Human_data);
Human Villain("Mike", Human_data);
//BODY
Human_data.set_life(5000);
Hero.print_life();
//END MAIN
return 0;
}
The inheritance could be correct, if all "humans" are also entities (remember that inheritance is an "is a" relationship).
But the implementation is flawed.
Instead of passing an Entity object to the Human constructor, and using the separate and distinct Entity object to control the "life", pass the life itself to the Human constructor, and use set_life on the Human object directly.
Something like this:
class Human : public Entity
{
public:
// By default humans start out with 50 in life
Human(std::string const& name, int life = 50)
: Entity(life), name(name) // Initialize the parent class, then the name
{
}
private:
std::string name;
};
int main()
{
Human hero("The Hero", 5000); // The hero will have 5000 life
Human villain("The Villain"); // The villain will only have 50 life
// Some stuff...
// Update the heroes life
hero.set_life(4000); // Uh oh, the hero have lost 1000 life!
// ...
}

Acessing subclass variable from base class object

Let's say i'm having the following classes in c++
class Animal{}
class Dog : public Animal {
int barkingVolume;
}
However, i don't have the header file for Dog class. But i have the object of Dog of type Animal at runtime.
The question is how I can access the variable barkingVolume?
Animal animalButDogObject;//someone has set the value at runtime
I need to access barkingVolume from animalButDogObject.
Actual scenario from COM/Directshow: I'm having IBaseFilter object which is of type IVendorFilter(custom filter from 3rd party vendor which extended IBaseFilter). While debugging using Visual studio i can see the type is IVendorFilter and it has variables which i need to change. However i cannot figure out how to do it. I cannot find anything like a reflection/evalutation in CPP
I'd rather comment than post an answer, but can't due to lack of reputation, so here we go.
This is pretty bad, but if you know the exact layout of the class you must access, you could just forward declare the whole thing and reinterpret_cast the object you need.
// FooBar.cpp or something
namespace FooBar
{
class Foo {};
class Bar : public Foo
{
public:
Bar(int ival, float fval) : ival(ival), fval(fval) {}
int ival = 0;
float fval = 0.0f;
};
}
// OtherFile.cpp
class ForwardDeclaredBar
{
public:
int ival;
float fval;
};
#include <iostream>
int main()
{
FooBar::Foo* foo = new FooBar::Bar(3, 2.7f);
auto bar = reinterpret_cast<ForwardDeclaredBar*>(foo);
std::cout << "ival = " << bar->ival << ", fval = " << bar->fval << std::endl; // shows expected values
return 0;
}
Again, this is pretty bad since any changes to the "real" class will mess up your result (reinterpret_cast will just shove whatever data it finds into the format you specified).
There are probably many other reasons which I've no idea about. I'm also unsure how well (if at all) this plays with more complex objects.
declare method on Animal (base) class and overwrite it on Dog (derived) class.
// Base class
class Animal
{
public:
virtual int getBarkingVolume() = 0;
};
// Derived class
class Dog : public Animal
{
private:
int barkingVolume = 8;
public:
int getBarkingVolume()
{
return barkingVolume;
}
};
In main method has Animal (base) type and each derived class that implements the appropriate method (getBarkingVolume) will be compatible with that type.
int main()
{
Animal* animal = new Dog();
std::cout<<"barking: "<< animal->getBarkingVolume();
}

C++ Inheritance: Do I have to repeat parent attributes in derived classes?

If I separate my classes into header/implementation files, is it possible to have inheritance without needing to redeclare inherited attributes in the child class?
Let me clarify with an example. Why is this allowed (taken from here):
#include <iostream>
using namespace std;
// Base class
class Shape {
public:
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived class
class Rectangle: public Shape {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
return 0;
}
But this isn't (try compiling here):
#include <string>
#include <iostream>
// HEADER FILE
class Person {
public:
virtual void speak() = 0;
protected:
std::string name;
std::string surname;
};
class Programmer : public Person {
public:
Programmer(std::string, std::string);
};
// CPP FILE
Programmer::Programmer(std::string name, std::string surname) :
name(name),
surname(surname)
{}
void Programmer::speak(){
std::cout << "My name is " + name + " " + surname + " and I like to code!";
}
I am not sure what is confusing. Member initializer list only allows to specify base class(es) or direct members of this class. Because of that, your second example is not compiling.
At the same time, derived classes have access to public and protected member of their base(s), so this is why first example is OK.
An interesting observation is that following code will compile:
Programmer::Programmer(std::string name_, std::string surname_) {
name = name_;
surname = surname_;
}
Note, this will mean name and surname will be first default-initialized (to empty strings) and than they will be assigned to the values passed in the Programmer constructor. This is efficiency loss, which might be very noticeable under certain circumstances.
The proper way of solving this idiomatically is buy giving Person a constructor which accepts two string arguments and initializes the members, and than calling this constructor from Programmer constructor.
In the Programmer constructor, in the initializer list the variables initialized can only be variables directly from that class or a base class constructor.
But in the body of the member functions/constructors inherited variables can be used, if they are effectively public or protected.

Looping through the derived classes by referencing the base class in C++

Sorry, if this has been asked before, just learning C++, had tried to search for it but not sure what the keyword is.
would it possible to do this?
class Car {
public:
void addColor(string c) {
color = c;
}
private:
string color;
}
class Honda:public Car {}
class Toyota:public Car {}
int main() {
vector<Car> v;
Honda *car1 = new Honda();
car1.addColor("green");
Toyota *car2 = new Toyota();
car2.addColor("blue");
v.push_back(car1);
v.push_back(car2);
for (int i = 0; i < v.size(); i++) {
cout << v[i].color << endl; // should output green, blue
}
}
if it's possible, what is the most right/effective way to do it?
EDIT 1
wow, thank you everybody!
your vector always hold the base type, Car, sliced. Look up for 'polymorphic STL collection' 'polymorphic vector' or like to see how to store the derived classes.
here is an example
There are two ways to handle this. Say we have the following class definitions:
#include <string>
class Car {
public:
Car(const std::string& color) : color(color) {}
virtual ~Car() {}
std::string color;
};
class Honda:public Car {};
class Toyota:public Car {};
Note I removed the setter and just made the member public. You may or may not want this, but for this example, it doesn't matter.
Here is a way by allocating everything on the stack, and taking the address of these objects. This is fine in this example case (car1 and car2 don't need to outlive the main function). In real code this may not be true (i.e. the objects may need to outlive the function in which they are created, see further below):
#include <iostream>
#include <vector>
int main() {
Honda car1("green");
Toyota car2("blue");
std::vector<Car*> cars; // vector of non-owning pointers
v.push_back(&car1);
v.push_back(&car2);
for(auto& car : cars) {
std::cout << car.color << "\n";
}
}
Alternatively, allocate your objects on the heap:
int main() {
std::vector<std::unique_ptr<Car>> cars; // vector of owning pointers
v.emplace_back(new Honda("green"));
v.push_back(new Toyota("blue"));
for(auto& carptr : cars) {
std::cout << carptr->color << "\n";
}
}
You were on the right way, there were just little things to fix :
Add a getter to the base class (Car);
Change the vector type (to a vector<Car*>);
Replace a.b by a->b when needed;
Fix missing semi-colon after classes definitions.
And here you go :
#include <iostream>
#include <vector>
using namespace std;
class Car {
public:
virtual ~Car ();
void addColor(string c) {
color = c;
}
string getColor () {
return color;
}
private:
string color;
};
class Honda:public Car {};
class Toyota:public Car {};
int main() {
vector<Car*> v;
Honda car1;
car1.addColor("green");
Toyota car2;
car2.addColor("blue");
v.push_back(&car1);
v.push_back(&car2);
for (int i = 0; i < v.size(); i++) {
cout << v[i]->getColor () << endl; // should output green, blue
}
}
By the way, if you want your subclasses to have their own methods to manipulate the color, just declare the methods as virtual in the car class, and you can redefine it in subclasses.
Another little point. You cannot make your vector be a vector<Car>. Because subclasses might not have the same size as the mother class (Imagine adding a int appeal; to your Honda class), because a vector can only store elements with the same size.

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;
}