Using base class function with derived class values - c++

I'm having problems getting a vector of objects to print the name of the derived class rather then the base class.
These are my classes
#include <vector>
#include <iostream>
using namespace std;
class Object
{
string name;
public:
string getName()
{
return name;
}
};
class Flashlight : public Object
{
string name = "Flashlight";
public:
string getName();
};
This is my main, it has a vector of the objects and at this point just needs to print out their names.
int main()
{
vector<Object> items;
items.push_back(*new Flashlight);
for(int i = 0; i < items.size(); i++)
{
cout << i+1 << " " << items.at(i).getName();
}
}
Right now if I assign something to the name in Object it will print that but its not using the derived classes values, I just want it to inherit the function then use its own values with it. I've tried implementing the function in the base classes(but seeing as I could have a lot of those in future it would lead to lots of redundant code) but that doesn't work either.

Instead of declaring variable 'name' in derived classes, initialize the variables value as custom value for that derived class. Also I would suggest you to make getName method as virtual. You also do not need to override getName method in derived classes if you just want to output name.

Try this way:
int main()
{
vector<Object *> items;
items.push_back(new Flashlight);
for(int i = 0; i < items.size(); i++)
{
cout << i+1 << " " << items.at(i)->getName();
}
}
Also as mentioned in another answer it would be good to use virtual methods read about it here.
What is more you need to use constructor to set value for variable name. You can read about them here
You should try this way:
class Object
{
private:
string name;
public:
Object() : name("Object")
{}
Object(string str) : name(str)
{}
string getName()
{
return name;
}
};
class Flashlight : public Object
{
public:
Flashlight() : Object("Flashlight")
{}
string getName();
};

Your code has two problems:
getName() is not virtual. This means that the actual function called is decided at compile time, based on the variable static type. So, if your variable is of type Object, Object& or Object* (or any const variation on those), function Object::getName() will be called, regardless of the actual type of the object referred to or pointed to by your variable (the dynamic type).
You have a vector<Object>, which means that all objects stored in it are of type Object. You can try to put a Flashlight object in it, but only the Object part will be copied into the vector. If you need polymorphism in a vector<>, you need a vector of pointers (or even better, smart pointers).
So you have to do two things to get the desired behaviour:
Declare function getName() as virtual string getName() (even
better, virtual const string& getName() const)
Declare items as vector<Object*> items (even better, use an
appropriate smart pointer such as unique_ptr<> instead of a raw
pointer)

Related

Subclass as argument in superclass's member function, C++

I'm new to OOP and I'm working on a C++ project. I isolated my problem to make answering easy but here's the real scenario:
I have a superclass member function, that modifies values inside the object that called it. The modification is based on a value coming from another object of the same class. This object is given to the function as the only parameter. Such as:
void BaseClass::function(BaseClass x) {}
However, I created a subclass. And if the parameter is a subclass type, I want to modify its unique attribute, too.
void BaseClass::function(DerivedClass x) {}
The problem is that the subclass is obviously defined later in the code.
I don't want it as two separate methods, because the calculation algorithm is already written inside, and also the solution I search for doesn't require to change the code at the places where the function is already in use. Besides, every other possibility that comes to mind (e.g. using typeid()) looks silly.
#include <iostream>
#include <string>
class Base
{
protected:
//common attribute
const std::string name;
public:
//constructor for common attribute
Base(const std::string nameString) : name(nameString) {}
//getter
std::string getName() { return name; }
//superclass as parameter
void test1(Base &example) { std::cout << example.getName(); }
//subclass as parameter (I'd want the line below to work)
//void test2(Derived &example) { std::cout << example.getNumber(); }
};
class Derived : private Base
{
protected:
//unique attribute
const std::string number;
public:
//constructor
Derived(const std::string nameString, const std::string numberString) : Base(nameString),
number(numberString) {}
//getter for unique attribute
std::string getNumber() { return number; }
};
int main ()
{
Base object = Base("whatever");
Base baseParameter = Base("base");
Derived derivedParameter = Derived("derived", "12");
object.test1(baseParameter);
//object.test2(derivedParameter);
return 0;
}
What is the standard way of doing it?
You could make test2 a template, and ensure that it's only used with types derived from Base:
template<typename Derived>
void test2(Derived &example)
{
static_assert(std::is_base_of_v<Base, Derived>);
std::cout << example.getNumber();
}
Here's a demo.

Assigning and Accesing derived class object to base class "pointer to pointer" object in C++

I am very much new to c++. I have a situation like: I have a base class which holds two virtual functions(NOT PURE). I have a derived class for this class where I implemented those virtual functions. Now in my main() function I created a pointer to pointer object to the base class. Now using this object how can I access the derived class object and functions.
I only want the pointer to pointer object of base class should be used to access derived class object.
BASE CLASS:
class another
{
public:
virtual void setName(){};
virtual string getName(){};
};
Derived Class
class use: public another
{
public:
string str;
void setName()
{
str = "USE CLASS";
}
string getName()
{
return str;
}
};
MY main() function:
int main()
{
another **an;
*an = new use();
an->setName(); //getting error
cout<<an->getName()<<endl; //getting error
return 0;
}
*an = new use();
Pointer an is not initialized, it cannot be dereferenced. Using doubled pointer (pointer to pointer) got no practical sense here. All tit does is to add another level of reference to code in this case. Expression that dereferences such pointer, results in value of pointer to class 'another', stored ... where? You had never created that storage, so such operation is an UB.
Legal variants of code:
int main()
{
another **an = new another*(); // creating storage for pointer
*an = new use();
(*an)->setName();
cout<<(*an)->getName()<<endl;
delete *an; // don't rely on OS to do so.
delete an;
return 0;
}
int main()
{
another **an = new another*(new use()); // doing this in one line
// storage of *an would be value-initialized by value returned
// from 'new use()' instead of default initialization
(*an)->setName();
cout<<(*an)->getName()<<endl;
delete *an; // don't rely on OS to do so.
delete an;
return 0;
}
int main()
{
another *an = new use();
// We don't need another pointer~ use an reference where required?
an->setName();
cout<<an->getName()<<endl;
delete an; // don't rely on OS to do so.
return 0;
}
PS. This declaration of class another technically is ill-formed, I may assume that you had skipped body of getName. It should cause compile time error about function's missing return value. If another is unusable class itself, you may declare methods as pure
class another
{
public:
virtual void setName() = 0;
virtual string getName() = 0;
};
An instance of such class or of a derived class that DOES NOT override those methods cannot be created, but it provides that "boilerplate" mechanics you're studying.
an is a pointer to pointer to another. *an returns a pointer to another. So you want (*an)->setName(); like so:
int main()
{
another **an;
*an = new use();
(*an)->setName(); //getting error
cout<<(*an)->getName()<<endl; //getting error
return 0;
}

How come accessing derived class member in base class pointer vector returns an error?

Streamlined Example of the problem:
#include <string>
#include <deque>
#include <iostream>
class Action{
public:
std::string name;
Action(std::string name){
this->name = name;
}
};
class Ability : public Action{
public:
int bar;
Ability(std::string name) : Action(name){}
};
int main(){
std::deque<Action*> foo;
Ability test("asdf");
test.bar = 122;
foo.push_back(&test);
std::cout << foo.at(0)->bar << std::endl;
return 0;
}
This creates an error, that there is no 'bar' member of 'Action'.
I realise that this relates to object slicing and I've attempted to use pointers, which allows the vector to push back the 'Ability' object but I cannot access its 'bar' member.
What am I missing?
First, a word from our sponsor: What is object slicing?
Now that you've read the above link, you can see that no slicing has taken place because the object was not copied into foo, only a pointer to the object was copied. The Ability is still intact, wherever in memory test sits.
But... Foo contains pointers to Action, not Ability. There is no way for a user of Foo to know if any given element of Foo is a reference to an Action, an Ability, or some other subclass of Action that they know absolutely nothing of. Very powerful stuff, the ability to work with something you don't even know exists, but this comes at a price: You have to work with it as something you do know. Users of Foo can only use the interface presented to them, that of Action. There are ways around this, such as dynamic_cast, but in most cases it best to stick with the provided interface and allow an overloaded method or operator to do black magic behind the scenes to do the correct thing for whatever the Action represents. If this means you have to
class Action{
public:
std::string name;
Action(std::string name){
this->name = name;
}
virtual int getbar() = 0; // pure virtual method that all subclasses
// of Action must implement
};
class Ability : public Action{
public:
int bar;
Ability(std::string name) : Action(name){}
int getbar()
{
return bar;
}
};
and later
std::cout << foo.at(0)->getbar() << std::endl;
so be it.

Compile time string assignment for run-time identification

I've been using a pattern in a library I'm creating that uses passes a String name of an object to its base object's constructor. I've tried using std::string and c-style strings but keep getting weird memory errors with Valgrind.
class Base {
public:
Base( std::string name ) : name(name) {}
virtual ~Base() {}
std::string getName() { return name; }
private:
std::string name;
};
class Derived : public Base {
public:
Derived() : Base("Derived") {}
};
int main() {
Base* derived = new Derived;
std::cout << derived->getName() << "\n";
delete derived;
}
(This compiles and runs fine in Valgrind)
Is something like this safe? I'm using 'const char*' instead of 'std::string' right now, is that safe?
Is there a safer alternative, preferably without using virtuals?
Edit: Is there a way to do this with templates? I don't want to use RTTI since it has the name mangled and I want the name to be 'normal' for use with scripting/data persistance.
Everything you do here is fine.
Templates would get you nothing because you still need to store a runtime pointer in the base class for dynamic identification.
Smart pointers would get you nothing because the lifetime of the string is the entire program. If you aren't computing anything, char const * and initialization from a string literal are ideal. If you are computing the string, then you can use static std::string const wrapped in a getter function.
class Derived : public Base {
public:
Derived() : Base(get_name()) {}
private:
static std::string const & get_name() {
static std::string const name = "Derived"; // or = compute_name();
return name;
}
};
This avoids the static initialization order fiasco. (The getter function receives an extra multithreading-safe guard from the compiler.) The lifetime of the string is the lifetime of the program. The Base may store a string const & or a char const *, it doesn't really matter. I would recommend char const * because the string reference could potentially be accidentally initialized with a temporary.

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/