This question already has answers here:
What is object slicing?
(18 answers)
Closed 1 year ago.
I'm having trouble trying to call the override function of an object that was appended to a vector. I'm not quite sure if I just don't completely understand pointers and references, so I'm not quite sure what to look for when debugging this issue.
Here is my code:
#include <iostream>
#include <vector>
class Task {
public:
Task(std::vector<Task> *list) {
list->push_back(*this);
}
virtual void Run() {
std::cout << "Called Task Run!" << std::endl;
}
};
class OverrideTask : public Task {
public:
OverrideTask(std::vector<Task> *list) : Task(list) {}
void Run() override {
std::cout << "Called Override Run!" << std::endl;
}
};
int main() {
std::cout << "Main method entered" << std::endl;
std::vector<Task> listOfTasks;
OverrideTask ot = OverrideTask(&listOfTasks);
Task t = Task(&listOfTasks);
for(int i = 0; i < listOfTasks.size(); i++) {
listOfTasks[i].Run(); // Will print "Called Task Run!" twice.
}
ot.Run(); // Prints "Called Override Run!"
t.Run(); // Prints "Called Task Run!"
}
When I loop through the vectors, it seems that I can't call the override function, but when I call them directly from the object, they seem to work. Can anybody point me in the correct direction?
Try store the base pointer in the vector instead like this. #Christophe asked me to remind that we store pointers which means the Task object
must remain alive. See also also #Quimby's note about using unique_ptr instead of Task *.
#include <iostream>
#include <vector>
class Task {
public:
Task(std::vector<Task *> *list) {
list->push_back(this);
}
virtual void Run() {
std::cout << "Called Task Run!" << std::endl;
}
};
class OverrideTask : public Task {
public:
OverrideTask(std::vector<Task *> *list) : Task(list) {}
void Run() override {
std::cout << "Called Override Run!" << std::endl;
}
};
int main() {
std::vector<Task *> listOfTasks;
OverrideTask ot = OverrideTask(&listOfTasks);
Task t = Task(&listOfTasks);
for(int i = 0; i < listOfTasks.size(); i++) {
listOfTasks[i]->Run();
}
}
Related
This question already has answers here:
Store derived class objects in base class variables
(6 answers)
Closed 5 months ago.
I am trying to figure out how to do oop in C++...
The issue lies with overrides. Consider the following code:
#include <iostream>
class Base {
public:
Base() { }
virtual void print() {
std::cout << "Base" << std::endl;
}
};
class Derrived: public Base {
public:
Derrived() : Base() { }
void print() override {
std::cout << "Derrived" << std::endl;
}
};
int main() {
std::cout << "Hello, World!" << std::endl;
Base b = Derrived();
b.print();
return 0;
}
When I run this program I would expect to see "Derived"! But I see "Base". So I would love to see this be possible in C++, as it is in languages like Scala, Java, C#, ... (event Rust!), but I am not sure if this is at all possible in C++.
If not maybe somebody can help me with the following situation:
std::string Value::any_to_string(std::any any) {
std::string s = NO_VALUE;
if (any.type() == typeid(Nothing))
s = std::any_cast<Nothing>(any).to_string();
if (any.type() == typeid(Boolean))
s = std::any_cast<Boolean>(any).to_string();
if (any.type() == typeid(Number))
s = std::any_cast<Number>(any).to_string();
if (any.type() == typeid(Lambda))
s = std::any_cast<Lambda>(any).to_string();
if (any.type() == typeid(Add))
s = std::any_cast<Add>(any).to_string();
if (any.type() == typeid(LiteralSet))
s = std::any_cast<LiteralSet>(any).to_string();
return s;
}
All of the above types inherit from a class named Value and override the method to_string(), though when casting the objects to a Value object, the definition in Value is called, rather than the one in the concrete type...
Thanks for helping me out!
Changing the main function to the following resolves the issue!
int main() {
std::cout << "Hello, World!" << std::endl;
Derrived derrived;
Base* b = &derrived;
b->print();
return 0;
}
this works too!
int main() {
std::cout << "Hello, World!" << std::endl;
Base* b = new Derrived();
b->print();
return 0;
}
I don't understand why the '''execute''' function of the Parent class is run. I feel like there are two instances: one for the parent class, one for the child class, but why? Indeed, this program is printing "1 Parent", as i expected "1 Child" or "0 Parent". If i uncomment the delay line, the output will be "1 Child".
I know there is a race condition in this program. This program was only made to understand the working principle of the inheritance in a multithreaded environment.
Thank you !
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <thread>
class Parent
{
public:
std::thread myThread;
int a;
Parent() {
this->myThread = std::thread();
this->a = 0;
}
void start()
{
this->myThread = std::thread(&Parent::execute, this);
}
virtual void execute() {
std::cout << a << " Parent" << std::endl;
}
virtual ~Parent() {
while(!this->myThread.joinable());
this->myThread.join();
}
};
class Child : public Parent
{
public:
Child() {
this->a = 1;
}
void execute() override {
std::cout << a << " Child" << std::endl;
}
~Child() {
}
};
int main()
{
std::cout << "Init" << std::endl;
Child * chld = new Child();
chld->start();
//std::this_thread::sleep_for(std::chrono::milliseconds(x));
std::cout << "Delete" << std::endl;
delete chld;
return 0;
}
Your program has undefined behavior which means "everything can happen".
You start a new thread which hold a pointer ( this ) to an object. This thread will later call a virtual method which means it needs to use data from the object it points to. The vtable pointer itself is some kind of data of the class. Because you delete your object from the other thread, the pointer ( this ) is simply pointing to a destructed object and accessing data ( vtable ) from an deleted object is undefined behavior.
Your observation is depending on the compiler implementation and maybe also on optimizing level. It is possible, that your compiler rewinds during deconstruction the vtable pointer down to the base class pointer. And as the memory of the object is not overridden from any other content ( which is even undefined! ) you can observe a call to the base function after destruction. But this is nothing you can rely on, as it is not allowed at all to use any object after destruction IF you use data members of the object which here is the vtable pointer.
In a short: Your code contains a bug and everything can happen as it is undefined behavior.
Your code exhibits the Undefined behavior (in your case resulting in Parent::execute call) because of the race condition between thread creation and Child object destruction. To fix it, you can define proper start and stop methods in your Parent class and call stop in Child destructor to prevent it from being destroyed before thread joins.
class Parent
{
public:
Parent(): myThread_() {
std::cout << "Parent CTor" << std::endl;
}
virtual ~Parent() = default;
bool start()
{
std::cout << "start" << std::endl;
if (myThread_.joinable()) {
std::cout << "already started" << std::endl;
return false;
}
myThread_ = std::thread([this]() {
execute();
});
return true;
}
bool stop() {
std::cout << "stop" << std::endl;
if (!myThread_.joinable()) {
std::cout << "not started" << std::endl;
return false;
}
myThread_.join();
return true;
}
virtual void execute() = 0;
private:
std::thread myThread_;
};
class Child : public Parent
{
public:
Child() {
std::cout << "Child CTor" << std::endl;
}
~Child() override {
stop();
}
void execute() override {
std::cout << "Child::execute()" << std::endl;
}
};
int main()
{
std::cout << "Init" << std::endl;
Child * chld = new Child();
chld->start();
std::cout << "Delete" << std::endl;
delete chld;
return 0;
}
I defined Parent::execute as abstract because probably you don't want it to be called at all and in case of another bug, at least you can get
terminate, pure virtual method called
This is nothing whatsoever to do with threads. You can reproduce the whole thing - including Undefined Behaviour - synchronously.
Single-threaded version of your classes:
#include <iostream>
#include <string>
class Parent
{
public:
int a;
Parent() : a(0) {}
virtual ~Parent() {}
virtual void execute() {
std::cout << a << " Parent" << std::endl;
}
};
class Child : public Parent
{
public:
Child() {
a = 1;
}
void execute() override {
std::cout << a << " Child" << std::endl;
}
};
and the single-threaded test cases demonstrating exactly the same behaviour:
int main()
{
Child c;
std::cout << "=== automatic lifetime ===\n";
std::cout << "virtual dispatch: ";
c.execute();
std::cout << "explicit static dispatch: ";
c.Parent::execute();
std::cout << "=== dynamic lifetime ===\n";
Child *pc = new Child;
std::cout << "virtual dispatch: ";
pc->execute();
std::cout << "explicit static dispatch: ";
pc->Parent::execute();
std::cout << "=== undefined behaviour ===\n";
delete pc;
std::cout << "explicit static dispatch: ";
pc->Parent::execute();
std::cout << "virtual dispatch: ";
pc->execute();
}
The last two output statements are swapped, because the last one crashed when I ran it (the penultimate is still UB, but happened not to crash)
=== automatic lifetime ===
virtual dispatch: 1 Child
explicit static dispatch: 1 Parent
=== dynamic lifetime ===
virtual dispatch: 1 Child
explicit static dispatch: 1 Parent
=== undefined behaviour ===
explicit static dispatch: 1 Parent
Segmentation fault (core dumped) ./a.out
Within JavaScript, you can pull off something like this:
function bunny() { alert("The bunny jumped."); }
var oldBunny = bunny;
function bunny() {
oldBunny();
alert("The bunny also ran.");
}
bunny(); // The bunny Jumped. The bunny also ran.
As one can see, the old "bunny" function had code appended to it by copying to a variable, then recreating the function with the same name. The copy of the original function runs, and the new code also runs.
I wish to replicate a similar mechanic in C++.
Now before you have a meltdown and start explaining the differences between static and dynamic languages, I get it. I'm not looking for something identical to what's provided, but I do desire something similar.
Furthermore, I'm not trying to do this to modify existing code; I wish to format my own source code to allow such a mechanic for other users to take advantage of.
One of the first ideas I had was to perhaps setup various macros within the code that could later be modified by other files.
Another idea would be to create a Signal and Slots system like in QT. Though I have no clue how to do such a thing myself.
Thank you for reading; I hope you have some suggestions.
Well, if you recognize which feature of JavaScript functions makes this possible, it's not too hard to do the same in C++. In JavaScript functions also have closures, which regular function in C++ don't have. But C++ lambdas are of a closure type. And if one defines bunny to be something which can both hold an object of a closure type, and be reassigned, you're all set.
The C++ standard library offers a nice default choice for this, in the form of std::function. We can just re-write your original JavaScript as follows:
std::function<void()> bunny = [] {
std::cout << "The bunny jumped.\n";
};
auto oldBunny = std::move(bunny);
bunny = [oldBunny] {
oldBunny();
std::cout << "The bunny also ran.\n";
};
bunny();
You can use functors.
#include <iostream>
#include <string>
class Base
{
public:
virtual std::string operator ()()
{
return "Base call";
}
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual std::string operator()()
{
return "Wrapper: " + Base::operator()();
}
};
int main()
{
Base* pFun = new Base;
std::cout << "Now check Base: " << (*pFun)() << std::endl;
delete pFun;
pFun = new Derived;
std::cout << "Now check Derived: " << (*pFun)() << std::endl;
return 0;
}
Assuming the goal is to allow the calling code to extend the program's functionality beyond what the initial code provided, I might use a user-updatable array of functor-objects, something like this:
#include <iostream>
#include <memory>
class Function
{
public:
virtual void Call() = 0;
};
typedef std::shared_ptr<Function> FunctionSharedPointer;
class OldBunny : public Function
{
public:
virtual void Call()
{
std::cout << "The bunny jumped." << std::endl;
}
};
class NewBunny : public Function
{
public:
NewBunny(FunctionSharedPointer oldFunction) : _oldFunction(oldFunction) {/* empty */}
virtual void Call()
{
_oldFunction->Call();
std::cout << "The bunny also ran." << std::endl;
}
private:
FunctionSharedPointer _oldFunction;
};
enum {
FUNCTION_BUNNY,
// other functions could be declared here later...
NUM_FUNCTIONS
};
// Our table of functions that the user can Call() if he wants to
static FunctionSharedPointer _functionTable[NUM_FUNCTIONS];
// Wrapper function, just to keep users from accessing our table directly,
// in case we ever want to change it to something else
void CallFunction(int whichFunction)
{
_functionTable[whichFunction]->Call();
}
// Another wrapper function
void SetFunction(int whichFunction, FunctionSharedPointer newFunctionDefinition)
{
_functionTable[whichFunction] = newFunctionDefinition;
}
// And another
FunctionSharedPointer GetFunction(int whichFunction)
{
return _functionTable[whichFunction];
}
int main(int argc, char ** argv)
{
// Our default function values get set here
SetFunction(FUNCTION_BUNNY, std::make_shared<OldBunny>());
std::cout << "before:" << std::endl;
CallFunction(FUNCTION_BUNNY);
// Now let's update an entry in our function table to do something different!
FunctionSharedPointer op = GetFunction(FUNCTION_BUNNY);
FunctionSharedPointer np = std::make_shared<NewBunny>(op);
SetFunction(FUNCTION_BUNNY, np);
std::cout << "after:" << std::endl;
CallFunction(FUNCTION_BUNNY);
return 0;
}
void bunny()
{
cout << "The bunny jumped." << endl;
}
void oldBunny()
{
bunny();
}
void newBunny()
{
bunny();
cout << "The bunny also ran." << endl;
}
#define bunny newBunny
int main()
{
bunny();
return 0;
}
If you don't need oldBunny(), just remove it.
I am getting memory leak issues in the following code. I understand there are some flows. But not sure. How to use shared_ptr in these scenarios? And in case I need to add more decorators, say Chocolate-Pista-Icecream, how to pass the pointer correctly such that it will get deleted at the exit?
class AbstractCream
{
public:
virtual void ShowFlavour() = 0;
virtual ~AbstractCream()
{
cout << endl << "AbstractCream-DTOR";
}
};
class IceCream :public AbstractCream
{
public:
void ShowFlavour()
{
cout << "IceCream";
}
~IceCream()
{
cout << endl << "IceCream Dtor";
}
};
class DecoratorCream :public AbstractCream
{
private:
std::shared_ptr<AbstractCream> AbCream;
public:
DecoratorCream(std::shared_ptr<AbstractCream>abs) :AbCream(abs)
{}
void ShowFlavour()
{
AbCream->ShowFlavour();
}
virtual ~DecoratorCream()
{
cout << endl << "DecoratorCream-DTOR";
}
};
class ChocolateCream : public DecoratorCream
{
public:
ChocolateCream(std::shared_ptr<AbstractCream>abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "CholocateCream added..";
DecoratorCream::ShowFlavour();
}
~ChocolateCream()
{
cout << endl << "ChocolateCream-DTOR";
}
};
class PistaCream : public DecoratorCream
{
public:
PistaCream(std::shared_ptr<AbstractCream> abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "PistaCream added..";
DecoratorCream::ShowFlavour();
}
~PistaCream()
{
cout << endl << "PistaCream-DTOR";
}
};
class StrawberryCream : public DecoratorCream
{
public:
StrawberryCream(std::shared_ptr<AbstractCream> abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "StrawberryCream added..";
DecoratorCream::ShowFlavour();
}
~StrawberryCream()
{
cout << endl << "StrawberryCream-DTOR";
}
};
int main()
{
std::shared_ptr <AbstractCream> ice1( new IceCream());
std::shared_ptr <PistaCream> pista1(new PistaCream(ice1));
std::shared_ptr <AbstractCream> ice2(new IceCream());
std::shared_ptr <ChocolateCream>choco1( new ChocolateCream(ice2));
pista1->ShowFlavour();
cout << endl;
choco1->ShowFlavour();
cout << endl;
getchar();
_CrtDumpMemoryLeaks();
return 0;
}
The problem doesn't seem to be the std::shared_ptr<...> use in your classes: that seems to be semantically correct (it is too much code to review in detail, though). Instead, I think your main() is wrong: you try to determine memory leaks at point in time when the objects are still alive. I'm not a Windows program but I'm pretty sure that _CrtDumpMemoryLeak() doesn't know about std::shared_ptr<...> and simply reports newed memory which isn't deleted, yet.
There are a couple of simply ways to change your main() to avoid the problem:
Put the allocation of objects into a block and report memory leaks after the block:
int main() {
{
std::shared_ptr <AbstractCream> ice1( new IceCream());
// ...
}
_CrtDumpMemoryLeaks();
}
Put the code doing the actual work into a separate function and in main() just call this function and report on memory leaks:
int actualMain() {
std::shared_ptr <AbstractCream> ice1( new IceCream());
// ...
}
int main() {
int rc = actualMain();
_CrtDumpMemoryLeaks();
}
Report memory leaks from the destructor of an object which is constructed early, e.g., first thing in main():
struct Reporter { ~Reporter() { _CrtDumpMemoryLeaks(); } };
int main() {
Reporter reporter;
std::shared_ptr <AbstractCream> ice1( new IceCream());
// ...
}
With all three approaches the std::shared_ptr<...>s are destroyed before memory leaks are reported. I'm pretty sure that all of these approaches make the memory leaks go away. My preference would be the use of the third approach.
That said, the way the std::shared_ptr<...> are passed isn't ideal from a performance point of view: increments the reference count each time. When passing it through multiple layers it is unnecessarily bumped up while calling and bumped down when returning from the call. There are multiple ways to fix that problem, too:
The simple approach is to pass the std::shared_ptr<...> as a constant reference:
ChocolateCream(std::shared_ptr<AbstractCream> const& abs)
: DecoratorCream(abs) {
}
It can be argued that the pass by reference inhibits copy elision. However, argument construct can only be elided over one level: when passing the object on to another function it is a named object and the rules for copy elision allow eliding the copy from named objects only for return and throw statements. It may still be reasonable to go that route for the inner-most constructor. Even then, the std::shared_ptr<...> should be moved when passing it on (in that case to the construction of the member variable):
DecoratorCream(std::shared_ptr<AbstractCream> abs)
: AbCream(std::move(abs)) {
}
If you want to pass the argument by value in the other constructors, too, you should, at least, std::move(...) the argument. Doing so should avoid the reference count but it still won't avoid all work as it needs to construct/destroy a std::shared_ptr<...> on each level. However, at least, the synchronized maintenance of the reference count would be avoided.
Since I mentioned a performance problem: stop using std::endl. It doesn't do you much good. In your use it just slows down the program.
class AbstractCream
{
public:
virtual void ShowFlavour() = 0;
virtual ~AbstractCream()
{
cout << endl << "AbstractCream-DTOR";
}
};
class IceCream :public AbstractCream
{
public:
void ShowFlavour()
{
cout << "IceCream";
}
~IceCream()
{
cout << endl << "IceCream Dtor";
}
};
class DecoratorCream :public AbstractCream
{
private:
std::shared_ptr<AbstractCream> AbCream;
public:
DecoratorCream(const std::shared_ptr<AbstractCream> &abs) :AbCream(abs)
{}
void ShowFlavour()
{
AbCream->ShowFlavour();
}
virtual ~DecoratorCream()
{
cout << endl << "DecoratorCream-DTOR";
}
};
class ChocolateCream : public DecoratorCream
{
public:
ChocolateCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "CholocateCream added..";
DecoratorCream::ShowFlavour();
}
~ChocolateCream()
{
cout << endl << "ChocolateCream-DTOR";
}
};
class PistaCream : public DecoratorCream
{
public:
PistaCream(const std::shared_ptr<AbstractCream> &abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "PistaCream added..";
DecoratorCream::ShowFlavour();
}
~PistaCream()
{
cout << endl << "PistaCream-DTOR";
}
};
class StrawberryCream : public DecoratorCream
{
public:
StrawberryCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "StrawberryCream added..";
DecoratorCream::ShowFlavour();
}
~StrawberryCream()
{
cout << endl << "StrawberryCream-DTOR";
}
};
//-------------------dec--------------------------------------------------------------//
struct DummyToLeakCheck
{
public:
~DummyToLeakCheck()
{
_CrtDumpMemoryLeaks();
}
};
int main()
{
DummyToLeakCheck myLeakChecker;
std::shared_ptr <AbstractCream> ice1( new IceCream());
std::shared_ptr <PistaCream> pista1(new PistaCream(ice1));
std::shared_ptr <AbstractCream> ice2(new IceCream());
std::shared_ptr <ChocolateCream>choco1( new ChocolateCream(ice2));
std::shared_ptr <StrawberryCream>straw1(new StrawberryCream(choco1));
pista1->ShowFlavour();
cout << endl;
choco1->ShowFlavour();
cout << endl;
straw1->ShowFlavour();
cout << endl;
getchar();
return 0;
}
Using a Leak-checker as mentioned in the first answer helped correcting the original code.Modified code. Ignoring std::endl as of now, since the purpose of the code is to try out smart pointers in decorator pattern.
I'm able to compile the following code where I pass a "callback" to an object (Table). What I'm trying to do now is inside Table, call the handle method defined in EventListener
#include <iostream>
#include <vector>
#include <memory>
class Table {
public:
struct Listener{
virtual void handle(int i) = 0;
};
std::vector<std::unique_ptr<Listener>> listeners_;
void add_listener(std::unique_ptr<Listener> l){
listeners_.push_back(std::move(l));
}
};
struct EventListener: public Table::Listener {
void handle(int e){
std::cout << "Something happened! " << e << " \n";
}
};
int main(int argc, char** argv)
{
Table table;
std::unique_ptr<EventListener> el;
table.add_listener(std::move(el));
return 0;
}
EDIT ****
This is what Im trying inside Table. It results in a segmentation fault:
for (auto t =0; t < (int)listeners_.size(); ++t) {
listeners_[t]->handle(event);
}
It doesn't work because you never created an object for it to be called on, just a pointer. The pointer inside the vector will be nullptr and therefore calling the function on it will crash. unique_ptr has absolutely nothing to do with this problem.
Half the problem is that Table cannot handle nullptr but doesn't check for it, and the other half the problem is that Table cannot handle nullptr but main passes one in anyway.
The iteration code is not the problem at all.
As mentioned in the answer by Puppy the line
std::unique_ptr<EventListener> el;
creates an empty std::unique_ptr. This causes the code for nivoking the
listeners to later dereference a nullptr.
A simple fix for your example is to create a listener and use that
when creating the unique_ptr:
struct EventListener: public Table::Listener {
void handle(int e){
std::cout << "Something happened! " << e << " \n";
}
};
// in main()
std::unique_ptr<NoOpListener> el{ new NoOpListener };
table.add_listener(std::move(el));
As mentioned in the comments your code should ensure that nullptr
isn't allowed. One way of doing this would be to add a check for
nullptr in add_listener and throw an exception or silently ignore
them. The first option is the better solution of the two as it
signals the caller that something is wrong.
But I don't see why you would store listeners in std::unique_ptrs.
The use for std::unique_ptr is for ownership. I do not see why the
observed instance should own the listeners. There is another alternative
that I think is better; use std::function<>() and pass it by value.
This disallows the use of nullptr and has the added bonus of accepting
not only function objects, but also normal functions and lambdas as shown
in the following code:
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
class Table {
public:
std::vector<std::function<void(int)>> listeners_;
void add_listener(std::function<void(int)> l) {
listeners_.push_back(l);
}
void invoke_listeners(int event)
{
for(auto l : listeners_) {
l(event);
}
}
};
struct NoOpListener {
void operator() (int i) {
std::cout << "NoOpListener::operator()(" << i << ")" << std::endl;
}
};
void cb(int i) {
std::cout << "cb(" << i << ")" << std::endl;
}
int main(int argc, char** argv)
{
Table table;
table.add_listener(NoOpListener{});
table.add_listener(cb);
table.add_listener([](int i) { std::cout << "[lambda](" << i << ")" << std::endl; });
table.invoke_listeners(10);
return 0;
}
NOTE: As you can see I also used the C++11 ranged-for construct for iterating
over the listeners.