inheritance problem - c++

I've messed up something.
Here is the code:
#include <iostream>
class connection_c {
private:
std::string data_;
void (*saveCallBack_)();
public:
connection_c(std::string &data) : data_(data) { std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;}
void registerCallBack(void(*cb)()) { saveCallBack_ = cb; }
};
class inst_c {
private:
static int id;
connection_c conn;
static void cb() { std::cout << __FUNCTION__ << " id = " << id << std::endl; }
public:
inst_c(connection_c &c, int a) : conn(c), id(a) {
std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
conn.registerCallBack(&cb);
}
};
class group_inst_c {
private:
connection_c conn;
inst_c i,j,k;
public:
group_inst_c(std::string data) : conn(data), i(conn,1), j(conn,2), k(conn,3) {}
};
int main() {
group_inst_c gi("asdf");
return 0;
}
What I want to achieve ;)
create a group of instances (group_inst_c)
it should initialize single connection for the group (connection_c)
each instance (inst_c) should use this connection (it will be serialized)
.. in addition each instance should register separate callback
For sure I've messed up with cloning, but I guess probably not only.
Can someone help me solve this puzzle? thx.

Your code creates a copy of your connection object for each instance. The original connection object is then only accessible by your group_inst_c. Is this what you want? If not, you need to change:
class inst_c {
private:
static int id;
connection_c& conn; // <-- Needs to be a reference.
in addition each instance should register separate callback
I'm not sure what you mean here. Are the callbacks supposed to be member functions? Then you need to use a "pointer to member function" (the ::*, .*, and ->* operators). If the callbacks are supposed to be regular functions, you should be okay with your current code. You'll just need to add this to class connection_c:
void doCallback(void) { (*saveCallBack_)(); }

If I understood that correctly (you want to call several callbacks from a single connection [object]), you need a list in connection_c to register the callbacks (just like delegates in C# if you know them).
If an event occurs to this connection, it has to know where to report. So you have to iterate through the callbacks somehow (call them one by one; you cannot call them all at once). The easiest, straightforward way is to use an STL list or maybe boost offers something appropriate.
Take a look at this: A C++ delegate class. In the main function, there's a vector defined that takes multiple callbacks. You could use this pattern in you connection_c class to add and not set a callback.

Try to keep it simple at first. There's always an opportunity to grow/improve the design later on. Below is some example code and here are a couple of things I was thinking about while building it:
1) As mentioned, keep it simple. For example, maybe the group concept can be a vector (i.e. inst_group_t) to start. You can always grow the design later as you learn more about it.
2) Try to reduce class dependencies. For example, maybe I do not need to have the connection as a member variable. I can pass it in when its needed (i.e. execute()). Maybe the callback doesn't need to be registered (i.e. execute()), since its 1 connection_c to many inst_c instances registering a callback for each inst_c would mean connection would have some container. Keep it simple :)
3) Try to use const and reference as much as possible (i.e. connection_c constructor). Less copy constructors/temp objects will be created.
#include <iostream>
class connection_c {
private:
std::string data_;
public:
connection_c(const std::string &data) : data_(data) {
std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;
}
};
class inst_c {
private:
int id;
public:
inst_c(int a) : id(a) {
std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
}
typedef void (*execute_callback_t)(int i);
void execute(connection_c& connection, execute_callback_t callback) {
callback(id);
}
};
void mycallback(int id) {
std::cout << "Instance number " << id << " executed" << std::endl;
}
int main() {
typedef std::vector<inst_c*> inst_group_t;
inst_group_t group;
std::string data;
connection_c connection(data);
for (int i = 0; i < 10; ++i)
group.push_back(new inst_c(i) );
for (int i = 0; i < 10; ++i)
group[i]->execute(connection, mycallback);
for (int i = 0; i < 10; ++i)
delete group[i];
return 0;
}

Related

Instantiate class inside a Constructor (c++)

Is the use of new/delete appropriate here? Or any way to avoid them?
The point: class myOptions need an instance of Submarine. The Parameter are known at the time the myOptions-Construcor is called.
#include <iostream>
#include <string>
class Submarine
{
public:
Submarine(std::string o)
{
std::cout << "create class Submarine: " << o << "\n";
}
~Submarine(){};
};
class myOptions
{
public:
myOptions(std::string o):option(o)
{
std::cout << "create class myOption: " << option << "\n";
submarine = new Submarine(option);
}
~myOptions()
{
delete submarine;
}
private:
std::string option{};
Submarine *submarine;
};
int main(void){
myOptions{"help"};
}
You don't need to use dynamic memory here:
class myOptions
{
public:
myOptions(std::string o):option(o), submarine(o)
{
std::cout << "create class myOption: " << option << "\n";
}
private:
std::string option{};
Submarine submarine;
};
If you really need to use dynamic memory allocation (and you are not allowed to use smart pointers), you must apply the rule of five to your class. Currently it will blow up your program anytime you decide to pass it by value.

Why is the copy constructor not called when objects are allocated on heap?

class Guitars
{
private:
int serialNumber{0};
float price{0.0};
// GuitarSpecs spec{};
public:
Guitars(int serNum, float price)
{
this->serialNumber = serNum;
this->price = price;
};
Guitars(const Guitars &s)
: serialNumber{s.serialNumber}, price{s.price}
{
std::cout << "Copy" << std::endl;
};
Guitars(Guitars &&source) noexcept : serialNumber{source.serialNumber}, price{source.price}
{
source.serialNumber = NULL;
source.price = NULL;
std::cout << "Move" << std::endl;
};
int GetSerial() const { return serialNumber; };
float GetPrice() const { return price; };
void SetPrice(float x) { this->price = x; }
};
class Inventory
{
private:
list<Guitars *> *guitarList;
public:
Inventory()
{
guitarList = new list<Guitars *>;
}
void AddGuitar(int serNum, float price)
{
Guitars *x = new Guitars(serNum, price);
// Guitars x(serNum,price);
guitarList->push_back(x);
}
void Display()
{
for (auto &&i : *guitarList)
{
std::cout << i->GetPrice() << " " << i->GetSerial() << endl;
}
}
~Inventory()
{
for (auto &&i : *guitarList)
{
std::cout << i->GetSerial() << " "
<< "deleted " << std::endl;
delete i;
}
std::cout << "List is deleted" << std::endl;
delete guitarList;
}
};
int main()
{
Inventory I;
I.AddGuitar(12050, 50.23);
I.AddGuitar(10000, 20.00);
I.Display();
return 0;
}
Can someone please explain to me why is the copy constructor not called in the code above?
When I created a list of Guitar pointers on the heap along with Guitar object on the heap with a pointer pointing to them and save those pointers in Inventory list, copy constructor is not called. Why is that happening and is this one more efficient since the program is not ganna create copies of object, its created once on the heap and we save the pointer with us.
Some detailed answer, based on you talking about optimization:
Your have the following code:
list<Guitars *> *guitarList;
void AddGuitar(int serNum, float price)
{
Guitars *x = new Guitars(serNum, price);
// Guitars x(serNum,price);
guitarList->push_back(x);
}
I think your reason to use all of those pointers is to be faster. If a Guitars object would be created on the stack as usual and then be pushed back, that would create a copy, true.
What you could do instead would be to define a move operation for Guitars and move the stack object into what you create in the list, like by calling the move constructor.
But even better would be to use std::list::emplace_back, like this:
list<Guitars> guitarList;
void AddGuitar(int serNum, float price)
{
guitarList.emplace_back(serNum, price);
}
In any case, if you talk about optimality, those pointers are not good. A pointer requires additional space, and every time the data is accessed, the pointer must be dereferenced. Also, as #PaulMcKenzie wrote in the comments, this can block the compiler from optimizing for you.
Also, making a list member itself a pointer, that is going with list<Guitars*>* guitarList; or list<Guitars>* guitarList;, is also not a good idea. The only reason I see is if you want to exchange the lists of two Inventory objects, but in that case, simply call std::swap on the lists.
If you drop the pointers, note how instantly every other code of yours becomes far easier. You don't even have to define your destructor at all.
(As for the actual question you asked, like #Jarod42 already wrote, copying pointers does not copy objects.)
(By the way, if the class Guitars represents a single guitar, then I'd go for the singular, Guitar.)
Edit:
I created a small series of tests with different ways to fill the list, using Guitars mostly unmodified. (I removed the assignments of the non-pointers to NULL though.) In any way, I did the following test setup:
#include <iostream>
#include <list>
class Guitar
{
private:
int serialNumber{0};
float price{0.0};
public:
Guitar(int serNum, float price)
{
std::cout << "Base" << std::endl;
this->serialNumber = serNum;
this->price = price;
}
Guitar(const Guitar& s)
: serialNumber{s.serialNumber}, price{s.price}
{
std::cout << "Copy" << std::endl;
}
Guitar(Guitar&& source) noexcept : serialNumber{source.serialNumber}, price{source.price}
{
std::cout << "Move" << std::endl;
}
};
void test_1()
{
std::cout << "test 1" << std::endl;
std::list<Guitar*> guitarList;
Guitar* x = new Guitar(1, 2.);
guitarList.push_back(x);
std::cout << std::endl;
}
void test_2()
{
std::cout << "test 2" << std::endl;
std::list<Guitar> guitarList;
Guitar x(1, 2.);
guitarList.push_back(x);
std::cout << std::endl;
}
void test_3()
{
std::cout << "test 3" << std::endl;
std::list<Guitar> guitarList;
guitarList.push_back(Guitar(1, 2.));
std::cout << std::endl;
}
void test_4()
{
std::cout << "test 4" << std::endl;
std::list<Guitar> guitarList;
guitarList.emplace_back(1, 2.);
std::cout << std::endl;
}
int main()
{
test_1();
test_2();
test_3();
test_4();
}
The output of this is:
test 1
Base
test 2
Base
Copy
test 3
Base
Move
test 4
Base
I hope this increases further understanding about how things work here.
The tests can be found under http://www.cpp.sh/35ld6
Also, I wanted to mention, if we talk about optimization, we'd have to talk about what we optimize. Right now, we have small lists of objects with almost no content. In that case, one would not optimize at all, as we talk about nanoseconds in difference.
The cases to think about are:
A small list of big objects that are easy to move. In that case, we need to make sure that no copy constructor is called, but move would be fine.
A small list of big objects that are hard to move. In that case, we only want to use the base operator, possibly by pointers as you initially did - but emplace_back also works and makes things easier. Note that the objects being hard to move would hint at a bad design for the class.
A big list of small objects. Here we want to use as few constructors as possible, including move constructors. We also don't want to use a list of pointers, as that would give us additional 64 bits per object, and a lot of derefencing later on. In that case, emplace_back really shines.
So in other words, you can't go wrong with emplace_back.

Any techniques or tricks to modifying existing functions in C++?

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.

C++ use string to call object member function

I have a superclass Entry and subclasses MusicAlbum, Book and Film. Instances of these subclasses are stored according to the name of the item ie Book1. The name and type of all these instances are stored in a vector cat_vector which is a vector of objects of class libCatalogue which simply stores the name and type:
class libCatalogue{
std::string name;
std::string type;
public:
libCatalogue(std::string name, std::string type);
std::string getname();
std::string gettype();
};
libCatalogue::libCatalogue(std::string name, std::string type) :name(name), type(type) {};
std::vector <libCatalogue> cat_vector;
Entries in the vector are made in the constructor eg.
MusicAlbum::MusicAlbum(std::string a, std::string b, std::string borrower)
: name(a), artist(b), Entry(borrower){
cat_vector.push_back(libCatalogue(name, "MusicAlbum"));
Each subclass has a member function called printdetails(). I want to use a loop to step through each entry in cat_vector and print the details of the entry but the following does not work:
int no = 1;
for (auto it = begin(cat_vector); it != end(cat_vector); ++it)
{
std::string name_ = it->getname();
std::string type_ = it->gettype();
std::cout << "Entry no. " << no << std::endl;
std::cout << "Name: " << name_ << std::endl;
std::cout << "Type: " << type_ << std::endl << std::endl;
if (type_ == "MusicAlbum"){
name_.printdetails(); //print using MusicAlbum member function
}
//etc...
no++;
I know it is because name_ is a string and not an object of any of the classes I want to call, but I haven't been able to find any way to convert it so far. Is there any way to tell the compiler that name_ is referring to an object of one of the subclasses?
C++ is a statically typed compiled language.You cannot create variables on fly. Fortunately, for cases like these, the work around is to use a lookup table. Generally this is achieved through a map where the key would be the string and the value would be the function you would want to associate and call for the particular string.
I know it is because name_ is a string and not an object of any of the
classes I want to call, but I haven't been able to find any way to
convert it so far. Is there any way to tell the compiler that name_ is
referring to an object of one of the subclasses?
when you qualify a member, the member name is qualified with respect to the type of the variable not with respect to the content. So the call name_.printdetails() would mean you are trying to invoke the member function printdetails for the instance of type std::string but std::string does not have a member function named printdetails.
A simple example to extend the above idea
struct Spam
{
enum { NO_OF_FUNCTIONS = 4 };
Spam()
{
lookup_callback["Foo1"] = std::bind(&Spam::foo1, this);
lookup_callback["Foo2"] = std::bind(&Spam::foo2, this);
lookup_callback["Foo3"] = std::bind(&Spam::foo3, this);
lookup_callback["Foo4"] = std::bind(&Spam::foo4, this);
}
void foo1() { std::cout << "Foo1" << std::endl; }
void foo2() { std::cout << "Foo2" << std::endl; }
void foo3() { std::cout << "Foo3" << std::endl; }
void foo4() { std::cout << "Foo4" << std::endl; }
void call(std::string name)
{
if (lookup_callback.count(name) > 0)
{
lookup_callback[name]();
}
else
{
std::cerr << "Invalid Function Call" << std::endl;
}
}
std::map<std::string, std::function<void(void)>> lookup_callback;
};
// Driver program to test above functions
int main()
{
std::string name;
Spam spam;
for (std::cin >> name; name != "quit"; std::cin >> name)
{
spam.call(name);
}
}
If you pass an instance of Entry around than you won't have a problem because you will be able to call:
it->entry->print_details();
If you don't want LibCatalogue to be aware of instances of Entry you can create a new class called Printable or something similar. This class will be held by Entry and by LibCatalogue. The `Printable class will have all the details required to print. That way you could call both:
it->printable->print_details();
entry->printable->print_details();
To augment #abhijit's answer, I often use static tables if the content is small and the usage is few.
// Typedef for a the function pointer
typedef void (*Function_Pointer)(void);
struct key_function_entry
{
const char * key_text;
Function_Pointer function;
};
void Process_Foo1_Request(void);
void Process_Bach_Request(void);
void Process_Eat_Request(void);
static const key_function_entry delegation_table[] =
{
{"foo1", Process_Foo1_Request},
{"Bah", Process_Bah_Request},
{"eat", Process_Eat_Request},
};
static const unsigned int delegation_entries =
sizeof(delegation_table) / sizeof(delegation_table[0]);
void Process_Request(const std::string& request)
{
for (unsigned int i = 0U; i < delegation_entries; ++i)
{
if (request == delegation_table[i].key_text)
{
delegation_table[i].function(); // Execute the associated function.
break;
}
}
}
An advantage here is that the table is static (one instance) and constant, so it can be placed into read-only memory. The table doesn't need to be built during runtime (like a std::map). The code references a table created during compilation phase. (It's an embedded systems thing, saving memory or placing stuff into read-only memory.)
For small number of entries, a linear search may be faster than a std::map.
For larger entries or very large number of accesses, an std::map may be preferred.

How to call method of wrapped object by unique_ptr?

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.