So basically I have a class SomethingSwimming and a derived class Ship. I want to implement that upon some event a Ship may lose its special qualities (such as holding lobsters hostage) and become just another SomethingSwimming object.
To illustrate:
class SomethingSwimming
{
protected:
int m_treasures;
public:
SomethingSwimming(int treasures): m_treasures(treasures) {;}
virtual int howManyLobstersOnBoard() {return 0; }
};
class Ship: public SomethingSwimming
{
protected:
int m_lobstersOnBoard;
public:
Ship(int treasures, int lobstersOnBoard): SomethingSwimming(treasures), m_lobstersOnBoard(lobstersOnBoard) {;}
int howManyLobstersOnBoard() {return m_lobstersOnBoard; }
};
void crash(shared_ptr<SomethingSwimming>& b)
{
b = make_shared<SomethingSwimming>(100);
}
int main()
{
shared_ptr<SomethingSwimming> a = make_shared<Ship>(100, 12);
cout << "How many lobsters on board: " << a->howManyLobstersOnBoard() << endl;
crash(a);
cout << "How many lobsters on board: " << a->howManyLobstersOnBoard() << endl;
return 0;
}
My question is how to crash the Ship so it becomes only SomethingSwimming (so it's not a Ship anymore) without reinitializing.
There is no way of cutting away rest of the object while keeping the identity of the base sub object. You can make a new copy of the base sub object, and throw away the derived object.
Currently you create an unrelated object in crash and thereby m_treasures won't be affected by m_treasures of the previously pointed object. To create a copy of the original base sub object, you can do:
b = make_shared<SomethingSwimming>(*b);
Alternatively, at the call site you can treat an indirectly referred base as if it were not part of a derived object by calling virtual member functions statically:
a->SomethingSwimming::howManyLobstersOnBoard()
This will result in the value of m_treasures regardless of the most derived type of the object.
Related
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();
}
I am new in programing and I am analyzing code with parent class fruit and child classes apple and pear. In this example there is pointer to parent class. After I extended this code I find out that using object I can access parent public members and all child members. Question is why do I need those pointers?
// are this pointer needed since I can use j.setWeight(11)
#include <iostream>
using namespace std;
class fruit {
private:
int weight;
public:
void setWeight(int x)
{
weight = x;
}
int getWeight()
{
return weight;
}
};
class apple : public fruit {
public:
void eat()
{
cout << "Now I am eating apple"
<< "=" << getWeight() << endl;
}
};
class pear : public fruit {
public:
void eat()
{
cout << "Now I am eating pear"
<< " = " << getWeight() << endl;
}
};
int main()
{
apple j;
pear k;
fruit* fruit1 = &j;
fruit* fruit2 = &k;
k.setWeight(5);
k.eat();
fruit1->setWeight(11);
apple apple;
apple.postaviTezinu(16);
apple.jelo();
return 0;
}
are this pointers needed since I can use j.setWeight(11) and results is same as
fruit1 -> setWeight(11) ... what s difference, thx
I suspect that the code you are looking at was written to demonstrate how pointers to base classes can be used with objects of derived classes. No, pointers are not necessary for the functionality of this learning exercise. In fact, that is probably the reason this functionality was chosen. Since you see how to accomplish the same thing without pointers, it should be easier for you to relate pointers to what you already know.
The key learning points I see in this exercise are
The same pointer type (fruit *) can point to objects of different types (apple or pear).
When using the pointer to the base class, you can access base class members.
When using the pointer to the base class, you cannot access derived class members. (Implied by omission; compare what is done with k to what is done with fruit1.)
You will need to move on to the more advanced lessons to learn when pointers are more useful than accessing objects directly (probably after eat() is turned into a virtual function). For now, just learn how the same task can be accomplished by different means.
(Sure, you could get that information here, but that code looks like it's part of a series. Continuing with that series might be the better way to learn.)
Since you're new to programming, learning polymorphism may be a bit advanced for you at this stage. To answer your question directly: No, you don't need pointers in your example code, and they are in no way helpful.
However, pointers to objects are often useful for:
Reducing unnecessary copying of objects
In the case of polymorphism (as in your example) pointers help in sections of your programme where you don't know which object type you're dealing with, or don't want to have to deal with them in different ways
Example:
#include <iostream>
#include <vector>
class A
{
public:
virtual void foo ()
{
std::cout << " I am A\n";
}
};
class B : public A
{
public:
virtual void foo ()
{
std::cout << " I am B\n";
}
};
void bar ( const std::vector <A*> & obj )
{
// Here it outputs the foo () function that is
// appropriate for the class
for ( unsigned int i = 0; i < obj . size (); ++i )
obj [i] -> foo ();
}
int main ()
{
A a1, a2, a3;
B b1, b2, b3;
// the below input style requires C++11,
// otherwise input them one-by-one
std::vector <A*> array {&a1, &b1, &a2, &a3, &b2, &b3};
bar ( array );
return 0;
}
The above array can store any A objects, including the inherited objects (it can't do this without pointers); and the bar function can still perform operations on the elements in the array without needing to know which object type they belong to within the inheritance tree (due to the virtual function). This is crucial for taking advantage of polymorphism, and saving on repetition of functions and code in general.
We know that, derived class members functions can be accessed through a base class pointer in C++ , provided that these member functions have to be virtual. Is there a means to access derived class member functions which are NOT virtual or pure virtual from base class pointer.
i.e. I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this?
For example, if I design a factory design pattern,
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
void Some2WheelerONLYSpecificOPeration()
{
}
};
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler" << endl;
}
void Some3WheelerONLYSpecificOPeration()
{
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler" << endl;
}
void Some4WheelerONLYSpecificOPeration()
{
}
};
// Factory method to create objects of different types.
// Change is required only in this function to create a new object type
Vehicle* Vehicle::Create(VehicleType type) {
if (type == VT_TwoWheeler)
return new TwoWheeler();
else if (type == VT_ThreeWheeler)
return new ThreeWheeler();
else if (type == VT_FourWheeler)
return new FourWheeler();
else return NULL;
}
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->Some2WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_ThreeWheeler);
basePtr->Some3WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_FourWheeler);
basePtr->Some4WheelerONLYSpecificOPeration(); // //HOW TO ACHIEVE THIS CALL
}
I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this ?
You cannot call a non-virtual member function of the derived class with a pointer to the base class.
You'll need a pointer to the derived class. The simplest method is to use dynamic_cast to get a pointer to the derived class, check whether the cast was successful, then call the derived class member function using a derived class pointer.
A better method would be to provide a virtual member function in the base class and implement it in the derived class.
You can do what you want with dynamic_cast, but this will lead to disappointing results at a code review. Instead, I pitch you go the same route you did with printVehicle
class Vehicle
{
public:
// without a virtual destructor you are walking into
// a very bad bug. The wrong destructor may be called.
virtual ~Vehicle()
{
}
virtual void printVehicle() = 0;
// Specific stuff that all children must provide
virtual void doTypeSpecificStuff() = 0;
// this is actually a bit of a ideological weird. I'm not sure I can call
// it a flaw. By making this factory function a member of Vehicle, Vehicle
// must now know its children. If this is the case, the VehicleType enum
// should probably be a member of Vehicle, but personally I think this
// factory should be a totally free function.
static Vehicle* Create(VehicleType type);
};
class TwoWheeler: public Vehicle
{
public:
void printVehicle()
{
cout << "I am two wheeler" << endl;
}
void doTypeSpecificStuff()
{
cout << "Doing two wheeler stuff" << endl;
}
};
Leaving out the other two classes and Vehicle::Create to save space.
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->doTypeSpecificStuff(); //HOW TO ACHIEVE THIS CALL
// leaking memory here, so
delete basePtr;
// but also look into std::unique_ptr. Much better suited to this behaviour
}
In fact, let's act on on that final comment about std::unique_ptr right now. A unique_ptr manages your dynamic allocations for you so you don't have to clutter up your code with deletes and run the risk of missing one or deleteing too soon. The unique_ptr's pointer is valid for as long as the unique_ptr is in scope. If you can compile, the pointer is good unless you done something silly like never point it at anything or manually remove the pointer.
And while we're at it, let's eliminate my earlier concerns about vehicle::Create.
First we define a free function to replace Create and return a unique_ptr. Since I hate to have to have if (ptr != NULL) checks all through my code to make sure an object really was created, let's also make a big stink about it when we can't match the provided vehicle type with class by throwing an exception.
And rather than a chain of if-else ifs we'll use a somewhat more elegant switch statement.
std::unique_ptr<Vehicle> SmarterVehicleFactory(VehicleType type)
{
switch (type)
{
case VT_TwoWheeler:
return std::make_unique<TwoWheeler>();
case VT_ThreeWheeler:
return std::make_unique<ThreeWheeler>();
case VT_FourWheeler:
return std::make_unique<FourWheeler>();
default:
throw std::runtime_error("Invalid Vehicle type");
}
}
And then we'll use this new function
int main()
{
try
{
std::unique_ptr<Vehicle> basePtr = SmarterVehicleFactory(VT_TwoWheeler);
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_ThreeWheeler);
// unique_ptr freed the TwoWheeler for us.
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_FourWheeler);
basePtr->doTypeSpecificStuff();
// just for laughs we will ask for a FiveWheeler, which we have not yet
// fully implemented
basePtr = SmarterVehicleFactory(VT_FiveWheeler); // will throw exception
basePtr->doTypeSpecificStuff(); // will not be executed
}
catch (const std::exception & exc)
{
cerr << "Rats! Something bad happened: " << exc.what();
// basePtr will be unmodified and still pointing to a FourWheeler
}
} // basePtr will go out of scope here and clean up our memory for us.
The beauty of this approach is no class knows anything about any other class. You can put Vehicle in a header with the SmarterVehicleFactory prototype and the list of vehicle types and hide everything else. The user sees nothing. Everybody is kept in the dark.
Why is that good? Because now you can change any of the above classes, except the Vehicle interface class, without having any effect on any of the other classes. This makes your code easier to maintain and debug.
I'm trying to find the best way to use polymorphism without using inheritance, because I want to avoid virtual calls. I was looking for a way to improve what I currently have (with no avail) and I stumbled on this question. This is the best I can do so far:
template<class VehicleDetails>
class Vehicle {
VehicleDetails details;
public:
VehicleDetails& getDetails() {
return details;
}
const VehicleDetails& getDetails() const {
return details;
}
void printDetails() const {
details.printDetails();
}
}
class TwoWheeler {
public:
void printDetails() const {
cout << "I am two wheeler" << endl;
}
void specificTwoWheelerMethod() const {
cout << "I am specific functionality" << endl;
}
}
Then you use it as such:
Vehicle<TwoWheeler> vehicle;
vehicle.printDetails(); // prints "I am two wheeler"
Unfortunately this complicates things. Now every class/struct or function that takes a vehicle must be templated, unless you know the type of vehicle.
template<class VehicleDetails>
void doGeneralVehicleThings(const Vehicle<VehicleDetails>& vehicle) {
// ...
}
On the plus side when you do know the type you can access specific functionality via the getDetails() method without any casting or runtime overhead involved:
void doTwoWheelerThings(const Vehicle<TwoWheeler>& twoWheelerVehicle) {
twoWheelerVehicle.getDetails().specificTwoWheelerMethod(); // prints "I am specific functionality"
}
I'm asking this because even tho it seems to work, I feel like it shouldn't. The goal is to have a collection of objects kept alive, and general access to them. This is what I have at the moment:
Take a base pointer access:
struct base { virtual void tick() = 0; }; //ptr access
With different types that inherit from it:
struct :public base
{
void tick() { cout << "im type 1" << endl; }
}type1;
struct :public base
{
void tick() { cout << "im type 2" << endl; }
}type2;
Then a container class that should be able to store any amount of these serialized:
class control
{
struct xtype //struct for organizing objects
{
vector<char>charbuf; //serialized object
}xtype_template;
vector<xtype>xtype_vec;
public:
template<typename T> base* tell_to(T &input) //take object, return (base*)
{
xtype_template.charbuf.resize(sizeof(input));
memcpy(xtype_template.charbuf.data(), (char*)&input, sizeof(input));
xtype_vec.push_back(xtype_template); //push back with template after filling
return (base*)xtype_vec[xtype_vec.size() - 1].charbuf.data(); //pointer to data
}
}xcontainer; //container object
Then call:
auto ptr = controller.tell_to(type1); //becomes base*
auto ptr2 = controller.tell_to(type2);
And you can access either static-sized serialized object, as well as its states, by doing:
ptr->tick(); //which will output "im type 1" to console
ptr2->tick() //"im type 2"
But is this legal? Do these serialized versions have an actual type? Is accessing a serialized object directly with a base pointer illegal or wrong?
Closest probable answer: as the return on is_trivially_copyable show false, objects might not be safe to manage after getting base inheritance.
Follow up: This approach seems to work, and fiddling with is_trivially_copyable, seems to suggest that making an object inherit methods from, makes it unsafe. Basic methods do not make it unsafe however, and that makes me wonder if the safety only applies to exporting between systems, saving to file, or transferring over the network. Maybe the check just assumes the virtual reference makes them unsafe?
Follow up 2: If the characters remain in the same spot in memory, does it matter how they are accessed? Id wager that the only real problem with this approach, is if the objects stored were to have elements that would change their size after being stored.
What you are doing is illegal. You can only memcpy an object as an array of chars when the object is TriviallyCopyable. And your object is not, since it has virtual functions.
Instead of doing this, you should simply store a (unique) pointer to newly allocated object, and avoid any casts to enforce hierarchy. Like this:
class xtype
{
std::unique_ptr<base> ptr;
public:
template<typename T> base* serial_acc(T &input) //take object, return (base*)
{
static_assert(std::is_base_of<base, T>::value, "Please use proper type");
ptr = std::make_unique<base>(input);
return ptr;
}
} xcontainer;
Working example given by user Andy Prowl
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
struct base
{
virtual void tick() = 0;
};
struct type1 : base
{
virtual void tick() override { cout << "im type 1"<<endl; }
};
struct type2 : base
{
virtual void tick() override { cout << "im type 2" << endl; }
};
struct controller
{
vector<unique_ptr<base>> objects;
void cycle_tick(){ for (auto const& ptr : objects)ptr->tick();}
void add_object(unique_ptr<base> obj){ objects.emplace_back(move(obj));}
};
int main()
{
auto t1 = unique_ptr<type1>(new type1);
auto t2 = unique_ptr<type2>(new type2);
controller ctrl_object;
c.add_object(move(t1));
c.add_object(move(t2));
ctrl_object.cycle();
}
I want to create a manager class which shall manage all the created objects of one type. Naturally this class should also create these objects. Therefore the client isn't allowed to create objects by himself, but instead must always use the manager class to do it.
Additionally the client is allowed to define his own classes which will be managed by one Manager.
template<class Type>
class Manager{
//...
Type* createInstance(){
Type* ptr = new Type();
//do sommething
return ptr;
}
};
The problem is: How do I restrict the creation of instances only to the manager class?
One possibility would be to declare the constructor as private and the Manager class as a friend class:
class A{
friend class Manager<A>;
private:
A(){}
~A(){}
};
Since the client is allowed to define own classes he could just declare the constructor public and the manager would still work without any problems. But the client would be able to create instances of those classes without the manager class witnessing it, resulting in bad behaviour/ressource management of the framework.
Is there a way to overcome this problem?
Managers of this sort are usually a bad pattern. The following code sample shows why.
It's the same problem as the one that says all destructors should be virtual. I use Manager to create a B, which derives from A, assign the object into an A* pointer. If it's destroyed as such, it goes through Manager::destroy(), which will probably not end well since it was created via Manager::make()
#include <iostream>
using namespace std;
template<class Type>
class Manager
{
public:
Manager(char *type)
{
mytype = type;
}
Type *make()
{
Type *ptr = new Type();
cout << "in Manager<" << mytype << ">::make() ptr->mytype is " << ptr->mytype << endl;
return ptr;
}
void destroy(Type *ptr)
{
cout << "in Manager<" << mytype << ">::destroy() ptr->mytype is " << ptr->mytype << endl;
delete ptr;
}
private:
char *mytype;
};
class A
{
friend class Manager<A>;
protected:
A()
{
mytype = "A";
cout << "in A()" << endl;
}
virtual ~A()
{
cout << "in ~A() mytype is " << mytype << endl;
}
char *mytype;
};
class B : public A
{
friend class Manager<B>;
protected:
B()
{
mytype = "B";
cout << "in B()" << endl;
}
virtual ~B()
{
cout << "in ~B() mytype is " << mytype << endl;
}
};
int main()
{
Manager<A> ma("A");
Manager<B> mb("B");
B *b = mb.make();
A *a = b;
ma.destroy(a); // This line calls Manager<A>::destroy. It should call Manager<B>::destroy.
return 0;
}
which produces the following as output:
in A()
in B()
in Manager<B>::make() ptr->mytype is B
in Manager<A>::destroy() ptr->mytype is B -- Oops - wrong destroy.
in ~B() mytype is B
in ~A() mytype is B
Which in turn means you can't use inheritance to it's full capability, which really defeats the purpose of using an OO language in the first place.
Depending on why you think you need a manager, there is probably a better solution.
If it's for memory management (unlikely given your original code snippet), overriding new and delete is worth taking a look at.
If it's for keeping track of all instances for processing purposes (e.g. objects in a game that get updated every game tick) then while it's a bit of a mental gearshift, a better solution is to integrate the manager into the class itself, as a set of static member functions and variables. Managers of this sort are almost invariably singletons, so making them static members / functions gets you to the same place semantically.
So you might have:
static set<A *> s_collection;
static void Heartbeat() // in class A
{
// lock s_collection here
for (auto it = s_collection.begin, end = s_collection.end() it != end; ++it)
{
// process *it
}
// unlock s_collection here
}
and then during A::A() you insert this into s_collection, and likewise during A::~A() you erase this.
Just be careful to use suitable synchronization primitives if you're multithreaded since most stl containers are not inherently thread safe.
You could use some variation of the passkey pattern to achieve this:
http://coliru.stacked-crooked.com/a/257860767a74a15e