I want to create ab object of the base class Foo that initializes the variable value to something I decide, I then want to create an object of the derived class Bar and the variable value I decided earlier sticks with Foo that Bar inherits, like a constant one time initialization for the variable value.
Is there a way to do this without passing in the value every time I create the Bar object like with the Foo object or make the class value default to 5?
Example:
// Base class
class Foo {
private:
int value;
public:
Foo() {}
Foo(int value) : value(value) {}
int getValue() { return value; }
};
// Derived class
class Bar : public Foo {
private:
public:
Bar() {}
};
Foo foo(5);
foo.getValue() // 5
Bar bar;
bar.getValue() // this I also want to be 5 now
You can do this with static variables, either in class scope or method scope (with the latter having some differences, like lazy initialization, thread safe initialization, etc. Although, it does not make a big difference in your use case, but it is good to keep the latter in mind as an option). For example
#include <iostream>
using std::cout;
using std::endl;
// Base class
class Foo {
private:
static int value;
public:
Foo() {}
Foo(int value) {
Foo::value = value;
}
int getValue() { return value; }
};
int Foo::value = 0;
// Derived class
class Bar : public Foo {
private:
public:
Bar() {}
};
int main() {
Foo foo(5);
cout << foo.getValue() << endl;
Bar bar;
cout << bar.getValue() << endl;
}
I have just provided you with a solution you want. Keep in mind that this might not be the best way to achieve what you want. An object's construction parameters should ideally only affect the current object.
Related
The goal of the code structure below is to be able to store pointers to objects of any class inherited from 'A'.
When I run this code, I get 0 written out, but what I'm trying to access is the 'B' object's 'num' value, which is 1. How can I do that?
As far as I know, when you create an inherited class's object, you create an object of the parent class too automatically. So can I somehow access the parent class object from it's child and set it's class member to match?
See minimal reproducible example below.
Update: Virtual functions solved the problem.
#include <iostream>
class A
{
public:
int num;
A()
{
num = 0;
}
};
class B : public A
{
public:
int num;
B()
{
num = 1;
}
};
class C
{
public:
A* ptr_array[2];
C()
{
ptr_array[0] = new B();
}
void print()
{
std::cout << ptr_array[0]->num << std::endl;
}
};
int main()
{
C* object_c = new C();
object_c->print();
return 0;
}
The problem is that you define a member num in A, and another member num in B. So an object of type B has two members called num, and you're leaving it to the compiler to choose which one to use -- which it does, according to logical rules which may be unfamiliar to you.
If you remove the line in num; from the definition of B, the code will work as you intend.
Your array is a red herring. You are only using one pointer. Might just as well have it as a member for the sake of the example.
I suppose you might need something like this (note, untested code).
#include <memory>
#include <iostream>
class A {
public:
A() : m_num(0) {} // use this instead of assignment in the c'tor body
virtual int getNum() { return m_num; } // this is **the** way to use inheritance
virtual ~A() = default; // required
private:
int m_num;
};
class B : public A {
public:
B() : m_otherNum(1) {}
virtual int getNum() { return m_otherNum; } // does something different from A
private:
int m_otherNum; // you could also call it m_num, but for clarity I use a different name
};
class C {
public:
C() : m_a (std::make_unique<B>()) {} // note, use this instead of new B
void print() {
std::cout << m_a->getNum() << std::endl;
}
private:
std::unique_ptr<A> m_a; // note, use this instead of A* m_a;
};
I have no way of knowing if this is really what you need (or you think you need). This is how inheritance is supposed to be used in object-oriented programming. You can use it in various other ways and produce correct (as far as the language definition is concerned) programs. But if this is the case, then (public) inheritance is likely not the best tool for the job.
The problem i've been facing is related to accessing an instance of a class, I'll explain it through a series of code snipets:
If I have a class Foo defined as defined below:
class Foo {
public:
Foo(){x=5}
private:
int x;
}
And I create an instance of that object in main as follows:
int main(){
Foo a;
}
I then want to access that instance of that object in another class and store it:
class Bar{
public:
Bar() {copy = a}
private:
Foo copy;
}
How would that be possible? Is there a way around this? Any help is appreciated!
The most natural way would be to pass the Foo object as an argument to the Bar constructor:
Bar(Foo a)
{
std::cout << a.x << '\n';
}
For the updated question, I might pass the object as a constant reference instead of by value:
Bar(Foo const& a)
: copy{ a }
{
}
This will initialize the member variable copy to be a copy of the Foo object that a references.
For the Qt special case, you should almost never make copies of QObject-derived objects. Instead you should have pointers to them:
class Bar
{
public:
Bar(Foo* a)
: pointer{ a }
{
}
private:
Foo* pointer;
};
#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.
Can someone tell me what is wrong with my program below? I am using a reference member variable in a class for polymorphism. I am expecting the second cout to say "derived2" but it says "base";
#include <iostream>
// Example program
#include <iostream>
#include <string>
class base
{
public:
virtual void print(){ std::cout<<"base"<<std::endl;}
};
class derived: public base
{
public:
virtual void print(){ std::cout<<"derived"<<std::endl;}
};
class derived2: public base
{
virtual void print(){ std::cout<<"derived2"<<std::endl;}
};
class foo
{
public:
base & bar;
base boo;
derived foobar;
derived2 foobar2;
foo(): bar(boo){}
void newfoo(base & newfoo){ bar = newfoo; bar.print();}
};
int main()
{
foo test;
test.bar.print();
test.newfoo(test.foobar2);
}
Output:
base
base
As mentioned by others, you cannot reassign a reference.
Whenever you do something like bar = newfoo you are not resetting the reference. Instead you are invoking operator= for bar with newfoo as an argument.
Therefore, in your case you are slicing your objects and (let me say) copying its base part in bar.
A kind of reference-like tool to which you can reassign exists in the standard template library and it's called std::reference_wrapper.
It follows an example based on your code that uses it and has the expected behavior:
#include<functional>
#include <iostream>
#include <string>
class base
{
public:
virtual void print() { std::cout<<"base"<<std::endl;}
};
class derived: public base
{
public:
virtual void print(){ std::cout<<"derived"<<std::endl;}
};
class derived2: public base
{
virtual void print(){ std::cout<<"derived2"<<std::endl;}
};
class foo
{
public:
std::reference_wrapper<base> bar;
base boo;
derived foobar;
derived2 foobar2;
foo(): bar(boo){}
void newfoo(base & newfoo){ bar = newfoo; bar.get().print();}
};
int main()
{
foo test;
test.bar.get().print();
test.newfoo(test.foobar2);
}
In this case, operator= actually rebinds the reference to the given object. Anyway, as you can see, in this case you must invoke get to access the underlying reference.
Note: set aside the example above, your code isn't the typical use case for a std::reference_wrapper.
I mentioned it only for the sake of completeness.
You can't 'reassign' the reference. When assignment operator is used with the reference, it assigns the underlying value.
Thus, bar = newfoo; simply assigns foo of the base type to foobar, slicing it in the process.
You could have a different behavior if you'd substitute references with pointers, which can be re-assigned.
bar is a reference to boo, and boo is of type base whatever you assign to it.
Assignment can only change a variables value, not its type.
Polymorphism does not work with references. Try this:
#include <iostream>
// Example program
#include <iostream>
#include <string>
class base
{
public:
virtual void print(){ std::cout << "base" << std::endl; }
};
class derived : public base
{
public:
virtual void print(){ std::cout << "derived" << std::endl; }
};
class derived2 : public base
{
virtual void print(){ std::cout << "derived2" << std::endl; }
};
class foo
{
public:
base* bar;
foo(): bar(0) {}
void newfoo(base* newfoo){ bar = newfoo; bar->print(); }
};
int main() {
foo test;
test.newfoo(new derived2);
}
#include <string>
#include <iostream>
class a { public: int x;};
class b : public a {public: int x; } ;
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
The code above compiles fine in clang 3.0 and g++ 4.5. However the output is junk (--i.e., not three). Since the compiler doesn't seem to mind, how do I get the code to behave ?
Secondly, If there is some way to make the above slice / conversion to work correctly, how bad would it be if I then did the following, provided a good reason to do it exists :
class c : public a { public: uint64_t x; };
Why I am interested in these semantics.
The reason I want to do this is this. I have a two class heirachies, where one heirarchy (the parent) aggregages objects, on the same heirarchy level, from the other(the child). I use a custom container for the aggregation. I want to typedef the container in the parent class (the typedefs have the same name), and declare the container with the same name at each level of the parent.
The class heirarchies are designed to contain less information at lower levels ( the base classes hold the least), therefore slicing makes perfect sense here.
Edit:
There you go, this should clear things up.
class A { int x; };
class B : public A {int y;};
class Ap {std::vector<A> entries;};
class Bp : Ap{std::vector<B> entries;};
The child B has more members than the child class A. However, I wan't to present a uniform interface for code that is only interested in the members of class A.
There is no way to do that if you directly set b::x. a::x and b::x are two different members, and the latter hides the former.
You can still access a::x on an object of type b with static_cast<a&>(bee).x = 3, but the fundamental problem is that the values of a::x and b::x on an object of type b are not synchronized.
If you abstract access to both x members with a "property getter/setter", then you can arrange for the setter on the derived class to also update the member of the base class. Or (maybe this is more appropriate?) you can make the member of the base class protected and use it from the derived class directly, slicing as you need just before returning from the getter.
huh ! its a bit complicated no ?
why don't you use :
class a
{
virtual void set( int value ) { x = value; }
protected :
int x;
};
class b : public a
{
virtual void setA( int value ) { a::x = value; }
or
virtual void setA( int value ) { b::x = value; }
or
virtual void setA( int value ) { a::x = value; b::x = value; }
protected:
int x;
} ;
There are two ways of constructing a software design; one way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
C.A.R.Hoare
According to Jon's answer, Since a::x and b::x are separate variables, furthermore since b::x masks a::x, if you wanted to get the correct semantics you need to provide a copy conversion constructor. The following code does the trick.
#include <string>
#include <iostream>
class b;
class a {
public:
a();
a(const b & bee);
int x;
};
class b : public a {public: int x; } ;
a::a() {}
a::a(const b & bee)
{
x = bee.x;
}
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
Maybe try something like this:
class A { int x; };
class B : public A {int y;};
class Ap {
public:
void Append(A *pa)
{
entries.push_back(pa);
}
A *GetA(size_t nIndex)
{
return entries.at(nIndex);
}
private:
std::vector<*A> entries;
};
class Bp : Ap
{
public:
B *GetB(size_t nIndex)
{
return dynamic_cast<B*>(GetA(nIndex));
}
};