I'm having some trouble figuring out how to assign values to member data when calling a virtual function through a heterogeneous list.
Here's an example of what I'm trying to do:
class A
{
protected:
virtual void func1();
private:
A * list;
}
class B: public A
{
protected:
void func1();
private:
int i1, i2;
}
Within main():
list = new A[10];
list[0] = new B;
list[0]->Func1();
Declaration of Func1():
void B::Func1()
{
int a, b;
cin >> a >> b;
list[0]->i1 = a;
list[0]->i2 = b;
// or can I just do this:
// i1 = a;
// i2 = b;
}
I'm looking for the appropriate way to access member data of a derived class within a function of the derived class if calling via a pointer of the parent class from main. Any help would be much appreciated!
While executing a virtual function you now that the type of the object is the type of class the function is defined in or a class derived thereof. That is, in your B::func1() function you know this points to a B object. The object may be of a type derived fromB but you still have everything present in B.
On the other hand, you don't know statically that list[0] points to B object. The code you have uncommented in your code does not work. The commented code looks OK
Related
For certain reasons, I want to have multiple instances of class A all have access to a single instance of class B. B has public member functions that allow objects of A to get data from B, but not to change it. I'm trying to do this by declaring an object of B in my main function, then passing it to the constructor when I declare objects of type A.
void main () {
B obj_b;
A A1(obj_b);
A A2(obj_b);
A A3(obj_b);
cout << A1.getfoo() << endl;
cout << A2.getfoo() << endl;
count << A3.getfoo() << endl;
}
class B{
private:
int foo = 9;
public:
int getfoo(){return foo;}
};
class A {
private:
B *bptr;
public:
A(B b){ this->bptr = &b; }
int getfoo(){ return bptr->getfoo(); }
};
This compiles and runs, but I get very weird results. The return values from getfoo are sometimes correct sometimes incorrect. Am I handling the pointers incorrectly? Is there a better way to do this?
In the A constructor, the argument b is a local variable, its life-time ends when the constructor function ends. You can't save a pointer to it, that pointer will become invalid immediately.
Either use smart pointers, or use a reference and constructor initializer lists:
class A
{
public:
// Pass by reference
A(B& b)
: b{ b } // Initialize the member variable b with the argument b
{
// Empty body
}
private:
B& b; // Reference to a B object
};
So i have been trying to use derived class data members from the base class and i am not able to figure out how to do that. I see a way to do this as just passing the member i need in parameter when i call the base class method but i was just thinking that there should be another way to do that. So i have replicated this as below.
#include<iostream>
using namespace std;
class B;
class A{
public:
display(){
cout<<cord<<endl;
}
int cord = 25;
};
class B : public A{
public:
B(){
A a;
a.display();
}
int cord = 30;
};
class C : public A{
public:
C(){
A a;
a.display();
}
int cord = 35;
};
int main(){
B b;
C c;
B.display();
}
The above code as giving output as
25
25
25
What i want it to give out is
30
35
30
Every way to do this will be appreciated, whatever is better and if you want to me add something or anything ask in comments, i'll do right away.
define a virtual getter like
virtual int getCord() const { return cord; }
in each class and call it in display
void display(){ cout << getCord() <<endl; }
and in the constructor of B and C you also need to replace
A a;
a.display();
just by
display();
else there is no chance you access to the value of the sub classes explicitly calling display on an instance of A
using derived class data members from base class method
This is because of that I let the redefinition of cord in B and C, but I do not recommend you to do that kind of redefinition in 'real' codes ;-)
Lets take the B constructor:
B(){
A a;
a.display();
}
In it you create a completely separate object a of type A, and call display on it. That display call will be using the a object, not knowing anything about the B class or its totally separate cord member variable at all.
One possible way to solve this is to create a constructor of A that takes the value of cord as an argument, pass the "correct" value in the B constructor initializer list, and then call the display function on this object:
struct A{
A() = default;
explicit A(int c)
: cord(c)
{
}
display(){
cout<<cord<<endl;
}
int cord = 25;
};
struct B : A{
B()
: A(30)
{
display(); // Equivalent to this->display();
}
};
Of course, you need to do something similar for the C class (or structure).
Note that I removed the member variable cord from the B class. That's because if you declare a new member variable with the same name as a member variable in a base class, then you effectively create a completely new member variable that is unrelated to the one in the parent class. And for the simple example you show there's no need to "override" the member variable, as it already exists in all child-classes as well.
Here is the code
,it is my homework using overriden methods teacher told us to analyze the code. I know the code is outputting 2, I have no clue how this code work.
public:
int a;
virtual void who(void) { a = 1; }
};
class B:public A{
public:
int a;
void who(void) { a = 2; }
};
class C :public B {
};
int main(void) {
A x; B y; C z; A *p;
p = &z;
p->who();
cout << z.a << endl;
system("pause");
return 0;
}
B overrides the who() function of its parent, A. This is called polymorphism. C inherits from B, but doesn't override anything; thus, it uses all of the implementation of B.
p is a pointer to an object of class A. One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class [1].
This means that when you call a member function of a pointer (p->who()), and the class of the object the pointer is pointing to overrides a member of its parent, is going to use the overridden member.
Sources:
[1] http://www.cplusplus.com/doc/tutorial/polymorphism/
as long as you create a function with same input and output with name; in short: same function declaration.. the new one will be used as you refer to one which has super class that has same function. in your case; super class for C is B and it doesn't see A, but B sees A and use all functions it has except what's B declare a new implementation for.
This is the code I have. Base class has member variable i and derived class also has same member variable name. Now client creates Base ptr pointing to derived and accesses member variable directly using i. I thought it would call derived member variable, instead it calls base class variable. I am not sure why this is?
#include<iostream>
using namespace std;
class A{
public:
int i;
A(int ii=5):i(ii){}
virtual void display(){
cout<<" In A :"<<i<<endl;
}
};
class B: public A{
public:
int i;
B(int ii=7):i(ii){}
void display(){
cout<<" In B :"<<i<<endl;
}
};
int main(){
A * aptr = new B();
cout << aptr->i <<endl; // expected B::i but gave A::i
aptr->display();
B bb;
bb.display();
return 0;
}
Is there a good reason for this. I thought like vptr is member variable of object(when new B was called) and this vptr calls correctly when we type aptr->display. Why isn't the same thing happening with i.
Member variables in C++ are not shadowed by inheritance the way virtual functions are.
If B inherits from A, and they both define a member named i, both of those variables exist and are independently part of the object.
Since your pointer has the type A*, the expression aptr->i will resolve to A's version of i.
As a side note, B can also explicitly access A's version of i, as long as it is not private.
class B: public A{
public:
int i;
B(int ii=7):i(ii){}
void display(){
cout<<" In B :"<<i<<endl;
cout<<" In A :"<<A::i<<endl;
}
};
This is what I wanted to ask and luckily was able to write in main func the stuff i needed.
Please check and let me know why A& and A instance behave differntly.
int main(){
A * aptr = new B();
cout << aptr->i <<endl;
aptr->display();
B *bptr = dynamic_cast<B*>(aptr);
bptr->display();
cout << bptr->i <<"\t" <<bptr->A::i<<endl;
A & aref = static_cast<A&>(*aptr);
cout <<endl <<"Called ref : "<<aref.i<<endl;
aref.display(); // here it calls B::display
A aa(*aptr);
cout <<endl <<"Called Inst : "<<aa.i<<endl;
aa.display(); // here it calls A::display
delete aptr;
return 0;
}
Question is why aref and aa behave differently?
My understanding is when instance of B was created using new B(). there were 2 variables in it, "i" and vptr of class B.
When aref is created, it called vptr of B for display,
but aa calls A::display,
While for both cases slicing is happening then how does it behave differently.
I am asking question in terms of memory is allocated to any class instance and when ptr of base is pointing to derived class. Hope you understand my confusion.
So say I have 3 classes: Base, A, and B.
Base is a base class for both class A and class B.
Base has a variable val that A and B can access.
How would I get it to work where I can set the val variable through class A, and it is reflected in class B?
For example:
I know this code below won't work because I am creating an OBJECT of the type a and b.
What I want to do is to simply have a and b share the same variable so that whenever a does something to it, it is reflected in b.
a aa;
b bb;
aa.SetVal(50000);
cout << aa.GetVal() << endl;
cout << bb.GetVal() << endl;
In the end I'd want both cout lines to print out 50000.
EDIT: The classes A and B will be doing different operations and just need to be able to access/change the val variable in base
You could make the member a static member of the base class, then all derived classes could access it, however any object of a derived that changes the static member would change it for every other object.
class Base
{
public:
int GetVal()
{
return val;
}
void SetVal( int newVal )
{
val = newVal;
}
private:
static int val;
};
// Need to instantiate the static variable somewhere
int Base::val = 0;
class A : public Base
{};
class B : public Base
{};
class Base {
static int value;
public:
virtual ~Base() { }
void setVal(const int& val) {
value = val;
}
int getVal() const {
return value;
}
};
int Base::value = 0;
class A : public Base {
};
class B : public Base {
};
#include <iostream>
int main() {
A a;
B b;
a.setVal(20);
std::cout << b.getVal(); // 20
}
That's a job for references, not for classes. Just have one class X and create a reference to the object:
X aa;
X& bb = aa;
aa.SetVal(50000);
std::cout << aa.GetVal() << std::endl;
std::cout << bb.GetVal() << std::endl;
The output will be:
50000
50000
Remember to always use the right tool for the job and keep things simple.
The main goal is that those two classes will be doing different things but will need to be able to access and share a single variable.
An idea to solve this is to extract the common variable in another class, namely S, which will be passed to A and B like this:
std::shared_ptr<S> s = new S();
A aa(s);
B bb(s)
Now, both aa and bb share the same S object and can modify it very easily. Notice that the constructor of both A and B should store the std::shared_ptr<S> as well:
class A { // and B
private:
std::shared_ptr<S> s;
public:
A(std::shared_ptr<S> as) : s(as) {}
};
The variable s will last as long as any of aa and bb is alive: when both aa and bb gets deallocated or go out of scope, the variable s will be deallocated as well.
If the type of the common variable should be on the stack, you can also just use references, but watch out for the lifetime of aa, bb and that variable:
int s = 0;
A aa(s);
B bb(s);
with:
class A { // and B
private:
int& s; // or any other type
public:
A(int& as) : s(as) {}
};
But as a general rule of thumb I'd avoid shared state between objects. Most of the time, depending on the context, you can refactor your code and get rid of the shared dependency.
If the shared value is static in the base class, then all instances of derived classes will see exactly that one base class member.
If the value is not static, then each instance of a class will have its own copy whether or not the value is in a base class.
Not sure I understand what you are trying to do. Do you want all instances of A and B to share the same value? if so, declare it as static in the base class.
if not, how do you want to choose which one will share the value?