I have the following Base Class.
class Furniture
{
public:
virtual void Collapse() = 0;
};
With derived classes:
class Table : public Furniture
{
public:
void Collapse()
{
Save(my_file);
}
protected:
void Save(char* filepath);
private:
char* my_file;
};
class Armoire : public Furniture
{
public:
void Collapse()
{
Save(my_file);
}
protected:
void Save(char* filepath);
private:
char* my_file;
};
class Chair : public Furniture
{
public:
void Collapse()
{
Save(); // note - no filepath
}
protected:
void Save();
};
After reading the comments, I have edited this question somewhat, to describe more accurately the problem in hand.
My problem is that all but one of the classes derived from Furniture define the Save() function with a parameter, like Table and Armoire are doing. It's only the Chair class that defines a Save() function with no parameter.
I want to somehow move the declaration of the Save() function - to be part of an interface, and have the derived classes provide the implementation. But that one class Chair that does not require a parameter means that I can't do this.
What is the best way to design this?
Use a default parameter in the base class:
virtual void Collapse( int seconds = 0 ) = 0;
Related
Is it possible to have concrete functions from a derived class override virtual functions from a separate base class? Like this:
// abstract Person
class I_Person
{
public:
virtual int age() = 0;
virtual int height() = 0;
};
// concrete person
class Person
{
public:
Person() = default;
int age();
int height();
}
class I_Worker : public I_Person
{
public:
virtual ~I_Worker() = default;
virtual void worker_func() = 0;
}
class Worker : public I_Worker, public Person
{
// override I_Person functions here with concrete Person functions
}
In my app, there are not just 2 functions in the Person class, there are more like 30. So Im trying to avoid redeclaring them in the concrete Worker class like this:
class Worker : public I_Worker, public Person
{
public:
int age() override {
return Person::age();
}
int height() override {
return Person::height();
}
void worker_func() override {}
};
Is there a way to do this or achieve a similar result?
Edit Made clear() and append() public in "ProductionNode"
I am trying to implement in C++ a similar example to the one presented at "Working effectively with Legacy code" page 359, the resulting diagram class at page 361.
It uses multiple inheritance; there is a base class "ProductionNode" which fully implements an interface called "Node", a second base class called "ProductionModelNode" which inherits from "ProductionNode" and from another interface called "ModelNode" which in turns inherits from the"Node" interface.
When I try to instantiate "ProductionModelNode" compiler claims that the methods defined at "Node" are not implemented, however they are implemented at "ProductionNode".
#include<algorithm>
#include <string>
class Node
{
public:
virtual void clear() = 0;
virtual void append(const std::string&) = 0;
};
class ProductionNode : public Node
{
public:
virtual void clear() override
{
m_name.clear();
}
virtual void append(const std::string& suffix) override
{
m_name += suffix;
}
protected:
std::string m_name;
};
class ModelNode : public Node
{
public:
virtual void reverse() = 0;
virtual void uppercase() = 0;
};
class ProductionModelNode : public ModelNode, public ProductionNode
{
public:
virtual void reverse() override
{
std::reverse(std::begin(m_name), std::end(m_name));
}
virtual void uppercase() override
{
std::transform(m_name.begin(), m_name.end(), m_name.begin(), ::toupper);
}
private:
int m_age;
};
int main(int argc, char** argv)
{
ProductionModelNode mn;
return 0;
}
This is a case of Dreadful Diamond on Derivation.
The class ProductionModelNode has two Node parent, one from ProductionNode is implemented, but the other from ModelNode is not.
Possible "trial" solutions:
Remove the inheritance from ModelNode
Implement clear and append in ProductionModelNode
Use virtual inheritance
Example using virtual inheritance:
class ProductionNode : virtual public Node
...
class ModelNode: virtual public Node
When you define a method with = 0 sign (for example: virtual void reverse() = 0;) it means that the method defined to be Pure virtual.
You must implement every "Pure virtual" method in every class that derive from the class that contains the "pure virtual" methods. (in your case Node class).
class ProductionModelNode : public ModelNode, public ProductionNode
{
public:
...
virtual void clear() override {
//implementation
}
virtual void append(const std::string&) override {
//implementation
}
...
}
I'm asked to implement an interface and I'm wondering what would be the best strategy to factorize the code as much as possible.
Here is the interface definition (I'm not supposed to change it):
#include <string>
class BaseIf
{
public:
virtual ~BaseIf() {}
virtual std::string getName() = 0;
};
class IntIf : public BaseIf
{
public:
virtual ~IntIf() {}
virtual int getValue() = 0;
};
class FloatIf : public BaseIf
{
public:
virtual ~FloatIf() {}
virtual float getValue() = 0;
};
I'll end up with IntImpl (implementing IntIf) and FloatImpl (implementing FloatIf). But I'm wondering where I should put any code common to those two classes (like the name attribute management or any other stuff required by BaseIf which is actually much bigger than in this MCVE).
If I create BaseImpl (implementing BaseIf's getName function) with the common code, and have IntImpl derive from it (and IntIf), then I need to also implement getName in it because it's reported as not implemented. And I also get double inheritance of BaseIf...
I was wondering if Pimpl pattern would help, then IntImpl would have a BaseImpl object as attribute (and only derive from IntIf), but then, again, I need to implement getName in IntImpl to "forward" the call to the BaseImpl attribute. So as BaseIf has actually many virtual functions this is just going to be a real pain to maintain.
Is there no smart solution/pattern making it possible to implement once only getName in a common place? Or is it just the interface that is bad and should be reworked?
This is the primary use case for virtual inheritance.
Despite all the stigma that surrionds multiple and virtual inheritance, there are no particular problems when oure interfaces (no data members) are virtually inherited. Here's the gist:
class BaseIf
{
public:
virtual ~BaseIf() {}
virtual std::string getName() = 0;
};
class IntIf : public virtual BaseIf
{
public:
virtual ~IntIf() {}
virtual int getValue() = 0;
};
class BaseImpl : public virtual BaseIf
{
public:
std::string getName () override { return "whoa dude"; }
};
class IntImpl : public virtual IntIf, public BaseImpl
{
public:
int getValue() override { return 42; }
};
full demo
With a deeper hierarchy one probably would have to virtually inherit implementation classes as well, which is not very convenient but still doable.
An alternative to virtual inheritance of implementation would be to stratify the implementation into a "building blocks" layer and the final layer. Building blocks are standalone and do not inherit other building blocks. (They may inherit interfaces). The final classes inherit building blocks but not other final classes.
class BaseBlock : public virtual BaseIf
{
public:
std::string getName () override { return "whoa dude"; }
};
class IntBlock : public virtual IntIf
{
public:
int getValue() override { return 42; }
};
class BaseImpl : public BaseBlock {};
class IntImpl : public BaseBlock, public IntBlock {};
full demo
One does need to made changes to the interfaces if there was no virtual inheritance in the hierarchy. These changes are however transparent (the clients code need not be changed, only recompiled) and probably beneficial anyway.
Without virtual inheritance, one would have to resort to lots of boilerplate.
class BaseBlock // no base class!
{
public:
virtual std::string getName () { return "whoa dude"; }
};
class BaseImpl : public BaseIf, public BaseBlock
{
public:
// oops, getName would be ambiguous here, need boplerplate
std::string getName () override { return BaseBlock::getName(); }
};
You can make a template class that implements the common part of an interface like this:
template <class IFACE> class BaseImpl : public IFACE
{
public:
std::string getName () override { ... }
}
and then
class IntImpl : public BaseImpl<IntIf>
{
public:
int getValue() override { ... }
}
The result is a simple single-inheritance chain. BaseIf <- IntIf <- BaseImpl <- IntImpl
Make sure you have a good reason for IntIf and FloatIf to exist, though -- in your MCVE they look like they don't need to be there at all.
You can provide default implementation for pure virtual functions:
struct A {
virtual void frob() = 0;
};
void A::frob() {
std::cout << "default";
}
struct B : A {
void frob() override {
A::frob(); // calls the default
}
};
If I'm reading your problem correctly, you'd like a default implementation for getName(). So solve that, simply provide an implementation and call it:
class IntIf : public BaseIf
{
public:
virtual ~IntIf() {}
virtual int getValue() = 0;
std::string getName() override {
return BaseIf::getName();
}
};
class FloatIf : public BaseIf
{
public:
virtual ~FloatIf() {}
virtual float getValue() = 0;
std::string getName() override {
return BaseIf::getName();
}
};
In the program hereafter, I have a class animal, that has derived classes cat and dog with the same public functions but different private functions. I would like to let the user decide during runtime which animal is being created. I have made a simple example that shows what I approximately want, but which obviously doesn't work. I don't know how to solve this and would like to have your help.
#include <cstdio>
class canimal
{
public:
int sound()
{
std::printf("...\n");
return 0;
}
};
class cdog : public canimal
{
public:
int sound()
{
std::printf("Woof!\n");
return 0;
}
};
class ccat : public canimal
{
public:
int sound()
{
std::printf("Mieau!\n");
return 0;
}
};
int main()
{
canimal *animal;
cdog *dog;
// I would like to let the user decide here which animal will be made
// In this case, I would like the function to say "Woof!", but of course it doesn't...
animal = new cdog;
animal->sound();
// Here it works, but I would like the pointer to be of the generic class
// such that the type of animal can be chosen at runtime
dog = new cdog;
dog->sound();
return 0;
}
You need to make the sound() method virtual:
class canimal
{
public:
virtual int sound()
^^^^^^^
This will make it behave exactly as you need.
For further discussion, see Why do we need Virtual Functions in C++?
In C++ 11 there is a new override keyword that, when used appropriately, makes certain types of errors less likely. See Safely override C++ virtual functions
I think you are looking to make sound() virtual. Read up on polymorphism in C++.
class canimal
{
public:
virtual int sound()
{
std::printf("...\n");
return 0;
}
};
You need to use virtual
i.e.
class canimal
{
public:
virtual int sound()
{
std::printf("...\n");
return 0;
}
};
class cdog : public canimal
{
public:
virtual int sound()
{
std::printf("Woof!\n");
return 0;
}
};
class ccat : public canimal
{
public:
virtual int sound()
{
std::printf("Mieau!\n");
return 0;
}
};
trying to understand methods and virtual function lets say i have 3 classes (the ones below)
class abstruct {void go()};
class animal:public abstruct {
public:
char* name;
void go(){}
};
class bird:public abstruct {
public:
char* name;
void fly(){}
};
class animalbird:public animal,public bird {
void go(){}
};
my question is how can go function from animal be accessed in the class animalbird?? i tried just to write void go(){} but it seems im wrong.what am i doing wrong?
void animalbird::go() {
animal::go();
}