I made class Head and class Derived from class Head. What should I do to have static (like a counter of object of class Head) variable which not increment in derived class.
In Head class:
class Head{
private:
static int counter;
string name;
int amount;
public:
Head(const string& n):name(n){
counter++;
}
};
int Head::counter=0;
and in class Derived:
class Derived: public Head{
public:
Derived(const string& n):Head(n){};
};
My target is to not increment counter when I create new object of class Derived.
What should I use? Virtual class, can someone explain me how to resolve this problem?
Make a conditional in your constructor (completely untested):
class Head{
private:
static int counter;
string name;
int amount;
public:
Head(const string& n, bool increment = true):name(n) {
if (increment) {
counter++;
}
}
};
int Head::counter=0;
and in class Derived:
class Derived: public Head{
public:
Derived(const string& n):Head(n, false){};
};
Segregate ctors, add another protected ctor for derived classes?
struct Base {
Base(const string &);
protected:
Base(nullptr_t, const string &);
};
struct Derived: Base {
Derived(const string &s): Base(nullptr, s) {}
};
You could just overload the constructor by changing the signature.
class Head{
private:
static int counter;
string name;
int amount;
public:
Head(){}
Head(const string& n):name(n) {count++;}
Head(const string& n,int a):name(n) {}
}
int Head::counter=0;
class Derived{
public:
Derived(const string& n):Head(n,1){};
}
Related
I have a class that manages a map of strings and pointers as such:
class DebugTab
{
public:
void pushItem(std::string&& name, std::unique_ptr<DebugItem> item);
private:
std::map<std::string, std::unique_ptr<DebugItem>> items_;
};
The pointers should be able to point to different types so to achieve this I made this simple abstract class:
class DebugItem
{
public:
virtual std::string asString() = 0;
};
And then made a few derived classes for fundamental types:
class DebugInt : public DebugItem
{
public:
DebugInt(int& i) : i_(i) {}
std::string asString() override {return std::to_string(i_);}
private:
int& i_;
};
class DebugFloat : public DebugItem
{
public:
DebugFloat(float& f) : f_(f) {}
std::string asString() override {return std::to_string(f_);}
private:
float& f_;
};
class DebugString : public DebugItem
{
public:
DebugString(std::string& s) : s_(s) {}
std::string asString() override {return s_;}
private:
std::string& s_;
};
My idea was that the person using DebugTab would create the item with the correct class on the heap using 'new' and then pass the pointer to pushItem like this:
DebugTab tab;
int var1;
float var2;
std::string var3;
tab.pushItem("var1", std::move(std::make_unqiue<DebugInt>(var1)));
tab.pushItem("var2", std::move(std::make_unique<DebugFloat>(var2)));
tab.pushItem("var3", std::move(std::make_unique<DebugString>(var3)));
I'm not very satisfied with this solution. I feel that it just isn't very intuitive to pass a heap pointer to a class that tracks already created variables.
Is there a better, simpler way of doing all of this that comes to mind, or is the system I have now sufficient?
Well, technically you can skip allocating them at callsite...
template<class T>
struct DebugConcrete: DebugItem {
T &t;
std::string asSring() const override {
return std::to_string(t);
}
};
class DebugTab {
template<class T>
void pushItem(std::string name, T &item) {
items_.emplace(std::move(name),
std::make_unique<DebugConcrete<T>>(item));
}
};
#define pushItem(...) pushItem(#__VA_ARGS__, __VA_ARGS__)
int main() {
int i;
DebugTab tab;
tab.pushItem(i);
}
So i have this part of code
class Robot
{
public: string Name;
public: explicit Robot(const string& Name) { this->Name = Name; }
public: Robot() { Name = "Robotic"; }
public: virtual ~Robot() = default;
public: virtual vector<string> GetCapabilities() = 0;
public: friend ostream& operator << (ostream&, const Robot&);
};
class TalkingRobot : virtual public Robot
{
public: explicit TalkingRobot(const string& Name) { this->Name = Name; }
public: virtual ~TalkingRobot() = default;
public: vector<string> GetCapabilities() { return { "Talking" }; }
};
class WalkingRobot : virtual public Robot
{
public: explicit WalkingRobot(const string& Name) { this->Name = Name; }
public: virtual ~WalkingRobot() = default;
public: vector<string> GetCapabilities() { return { "Walking" }; }
};
class VaxBot : public TalkingRobot, public WalkingRobot
{
public: explicit VaxBot(const string& Name):TalkingRobot(Name), WalkingRobot(Name) { this->Name = Name; }
public: virtual ~VaxBot() = default;
public: vector<string> GetCapabilities() { return { "Talking","Walking" }; }
};
They have a virtual function GetCapabilites().
Is there a way to rewrite GetCapabilites() in my VaxBot class to return all the inherited classes return values so that i dont have to explicitly write them like i did in here?
There isn't a simple one-line way in standard C++ to implement this sort of thing. For example, there is no way for a derived class to iterate over all its base classes, and call some member function in every base to collect the results, without explicitly naming all the bases/members separately.
It is possible to call the inherited functions, and collect their results into a single vector. For example;
std::vector<std::string> VaxBot::GetCapabilities()
{
std::vector<std::string> values(TalkingRobot::GetCapabilities());
std::vector<std::string> more_values(WalkingRobot::GetCapabilities());
values.insert(values.end(), more_values.begin(), more_values.end());
return values;
}
The above can be extended if you have more than two such bases. That means explicitly replicating code but, as I said in my opening paragraph, there is no way to implement this sort of machinery implicitly.
There are other problems with your code, but you haven't asked about those, so I won't address them. And, for readability, don't use the text public: on every line. Posting code that is unnecessarily unreadable is an effective way to reduce your chances of getting useful help, since it sets other people's teeth on edge.
class Robot
{
public: string Name;
public: vector<string> Capabilities;
public: explicit Robot(const string& Name) { this->Name = Name; }
public: Robot() { Name = "Robotic"; }
public: virtual ~Robot() = default;
public: vector<string> GetCapabilities() { return this->Capabilities; }
public: friend ostream& operator << (ostream&, const Robot&);
};
class TalkingRobot : virtual public Robot
{
public: explicit TalkingRobot(const string& Name) {
this->Name = Name;
this->Capabilities.push_back("Talking");
}
public: virtual ~TalkingRobot() = default;
};
class WalkingRobot : virtual public Robot
{
public: explicit WalkingRobot(const string& Name) {
this->Name = Name;
this->Capabilities.push_back("Walking");
}
public: virtual ~WalkingRobot() = default;
};
class VaxBot : public TalkingRobot, public WalkingRobot
{
public: explicit VaxBot(const string& Name):TalkingRobot(Name), WalkingRobot(Name) { this->Name = Name; }
public: virtual ~VaxBot() = default;
};
You could utilize multiple inheritance constructors to store Capabilities.
I got an Abstract Baseclass which looks like this:
class AbstractClass {
public:
virtual ~AbstractClass() = 0 {}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
Now I got many derived Classes and I want to implement them like this
class DerivedClass1 : public AbstractClass{
public:
DerivedClass1() = default;
~DerivedClass1() = default;
private:
std::string m_Name = "DerivedClass1";
};
int main() {
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
I dont want to override GetName() everytime i derive a Class, is this possible?
Edit:
I got a Linker Error. Error LNK2019.
Use only one name, in the base class, and a constructor with a parameter:
class AbstractClass{
public:
AbstractClass(const std::string& name) : m_Name(name){}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
DerivedClass1 : public AbstractClass{
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
int main(){
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
There seems to be no reason for making the base class abstract, but if you do need that, even a pure virtual destructor must have a definition, or you will get a linker error, because it's needed when destroying derived objects.
Also, if the destructor didn't exist, when would m_Name be destroyed?
class Abstract
{
public:
virtual ~Abstract() = 0;
};
Abstract::~Abstract() {}
This makes a class that can't be instantiated, but whose derived classes can still be destroyed.
That's not how you "override" GetName(). You can either make GetName() virtual and override it in your derived classes:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
virtual std::string GetName() const { return "AbstractClass"; }
private:
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() = default;
std::string GetName() const override { return "DerivedClass1"; }
};
Or you can set m_Name in your derived classes by passing it to the base class constructor:
class AbstractClass {
public:
AbstractClass(const std::string& name) : m_Name(name) {}
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
Or you can set it in the derived's class constructor:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass() { m_Name = "DerivedClass1"; }
};
You get the link error because the destructor for AbstractClass needs to be defined even if it is empty.
AbstractClass::~AbstractClass()
{
// Compulsory virtual destructor definition,
// even if it's empty
}
LIVE on Wandbox
Regarding overriding getName: you do not have to. If you do not provide an implementation in the derived class, the one inherited one is used.
Code sugest that problem is how to get a class name? But this is not clearly stated in question (XY problem)
How to handle class name?
You can use RTTI:
class ClassName {
public:
virtual ~ClassName() {} // just to enable RTTI for all decendants
std::string getClassName() {
return typeid(*this).name();
}
};
https://wandbox.org/permlink/LvPdA37arMr0LFQW
But as you can see it adds some extra prefix (it is compiler depended). boost can clean it up:
https://wandbox.org/permlink/8XiB7yVOM0wYVxpl
I have a Base class with several derived classes:
class Base {
private:
long id;
public:
Base() {}
~Base() {}
Base &operator = (long temp) {
id = temp;
return *this;
}
};
template <class C>
class Temp1 : public Base {
public:
Temp1() {}
~Temp1() {}
//do something;
};
template <class C>
class Temp2 : public Base {
public:
Temp2() {}
~ Temp2() {}
//do something;
};
class Executor1 : public Temp1<int> {
public:
Executor1() {}
~Executor1() {}
};
class Executor2 : public Temp2<char> {
public:
Executor2() {}
~Executor2() {}
};
I want those classes to support operator =.
e.g:
int main()
{
long id1 = 0x00001111, id2 = 0x00002222;
Executor1 exec1;
Executor2 exec2;
exec1 = id1; //exec2.id = id1;
exec2 = id2; //exec2.id = id2;
}
I define operator = in Base whose declaration is Base &operator = (long);.
But there is a problem clearly that = doesn't work to derive classes. So I have to define operator = totally do the same thing to every Executor.
How to deal with this case in Base in a better way?
You have to pull the =-operator into the scope of the class:
class Base
{
public:
long id;
Base& operator=(long id)
{
this->id = id;
return *this;
}
};
class Temp2
: public Base
{
public:
using Base::operator=;
};
You have to pull the operator= into the scope because the implicitly generated copy operator= of Temp2 was hiding the operator= of Base. Got this hint from #Angew from's comment.
class ZooAnimal {
public:
virtual void draw();
int resolveType() {return myType;}
protected:
int myType;
};
class Bear : public ZooAnimal {
public:
Bear (const char *name) : myName(name), myType(1){}
void draw(){ };
private:
std::string myName;
};
void main()
{
}
When I am compiling above code I am geeting following error
error C2614: 'Bear' : illegal member initialization: 'myType' is not a base or member
Why am I getting the above error, as we can access protected member from the derived class?
You can't initialize base class member in derived class initializer lists.
You'll need to provide a constructor to the base class:
class ZooAnimal {
public:
ZooAnimal(int type) : myType(type) {}
virtual void draw();
int resolveType() {return myType;}
protected:
int myType;
};
and call it from the derived class:
class Bear : public ZooAnimal {
public:
//here//
Bear (const char *name) : ZooAnimal(1), myName(name) {}
void draw(){ };
private:
std::string myName;
};