My scenario is simplified in the following example:
#include <iostream>
#include <vector>
using namespace std;
class C;
class A
{
protected:
C * cPointer;
A();
virtual void updateList() = 0;
void callFunc();
};
class B : public A
{
private:
vector<int> list;
void updateList();
public:
void callFromA();
};
class C
{
friend class A;
friend class B; // I want to get rid off this declaration
private:
int sum;
void set_sum( int val );
public:
static C * getCPointer();
};
A::A()
{
cPointer = C::getCPointer();
}
void A::callFunc()
{
updateList();
}
void B::updateList()
{
list.push_back(2);
list.push_back(4);
int s = 0;
for( unsigned int i=0; i<list.size(); i++ )
{
s += list[i];
}
cPointer->set_sum(s);
}
void B::callFromA()
{
callFunc();
}
void C::set_sum( int val )
{
sum = val;
cout << "Sum at C is: " << sum << endl;
}
C * C::getCPointer()
{
static C cPointer;
return & cPointer;
}
int main( int argc, char ** argv)
{
B b;
b.callFromA();
return 0;
}
This example works fine. But I want to get rid of the "friend class B" declaration in class C and achieving similar functionality. Actually I want to have either of the following:
accessibility of C::set_sum() from B::updateList() which will not be possible without the "friend class B" declaration in class C.
accessibility of B::list in A::callFunc() whereby I can push the logic from B::updateList to A::callFunc() which basically means ability to access a list in the derived class from the base class. In this way, I will be able to access the set_sum() in A::callFunc() due to "friend class A" declaration in class C.
Any idea to achieve this without involving major design changes is desirable!
Thanks!
I'm not sure if I understand all your restrictions, but maybe this works better for you. Basically, you can access B::list from A using a virtual function. I've commented the changes in the code.
#include <iostream>
#include <vector>
using namespace std;
class A;
class C
{
friend class A;
private:
int sum;
void set_sum(int val);
public:
static C * getCPointer();
};
class A
{
protected:
C * cPointer;
A();
virtual int getS() = 0; // virtual function to calculate data from vector in derived class B
virtual void updateList()
{
cPointer->set_sum(getS()); // A is friend of C, so you can access B data from A
}
void callFunc();
};
class B : public A
{
private:
vector<int> list;
void updateList();
int getS() // concrete implementation to access vector data
{
int s = 0;
for (unsigned int i = 0; i < list.size(); i++)
{
s += list[i];
}
return s;
}
public:
void callFromA();
};
A::A()
{
cPointer = C::getCPointer();
}
void A::callFunc()
{
updateList();
}
void B::updateList()
{
list.push_back(2);
list.push_back(4);
A::updateList(); // Call to super implementation
}
void B::callFromA()
{
callFunc();
}
void C::set_sum(int val)
{
sum = val;
cout << "Sum at C is: " << sum << endl;
}
C * C::getCPointer()
{
static C cPointer;
return &cPointer;
}
int main(int argc, char ** argv)
{
B b;
b.callFromA();
return 0;
}
You can not access members of derived classes inside the base class, period. The object at hand might be of the base class, or even of a completely unrelated derived class, with guaranteed "interesting" consecuences. Any design asking for doing so is seriously broken, and needs rethinking.
You can make the member function of the base class which wants to do so virtual, and redefine it in the derived class to do whatever perversion you have in mind. Meanwhile, the chaste member of the base class can just refuse if called, signalling the mistake in a sane way. That way you get a guarantee that nothing too untoward can happen.
Related
#include<iostream>
using namespace std;
class Base {
private: int b;
protected: int a;
public: int c; void setdata(); int getdata(); };
void Base ::setdata() { int a = 10; int b = 20; int c = 30; }
int Base::getdata() { return b; }
class Derived: public Base { public: void display() { setdata(); cout << a << endl << getdata() << endl << c << endl; } };
int main() { Derived xyz; xyz.display(); return 0; }
Lets look at your setdata function:
void Base ::setdata() { int a = 10; int b = 20; int c = 30; }
Inside it you define three new variables a, b and c, which are totally unrelated with the Base member variables of the same name.
That means the Base member variables will be uninitialized and with indeterminate values. And printing them leads to undefined behavior.
Your setdata function should set the Base member variables, which are already declared and defined and can be used as-is:
void Base ::setdata() { a = 10; b = 20; c = 30; }
With that said, a better solution is to use a constructor to initialize the member variables instead of a separate function:
class Base
{
public:
Base()
: a{ 10 }, b{ 20 }, c{ 30 } // An initializer list, to initialize members
{
// Empty body of constructor function
}
// Rest of class, without the setdata function ...
};
In multiple inheritance,where all the base class contains same function name with different functionality, we can access the protected function from particular base class using "::" scope resolution operator.
However, I tried something else. I created the objects of the base class in inside the child class. And tried calling the function using through object of that particular class.
But I was getting the following compiler error:
"‘void A::func(int&)’ is protected within this context."
Please let me know where did i go wrong.
#include <iostream>
using namespace std;
class A
{
protected:
void func(int & a)
{
a = a * 2;
}
};
class B
{
protected:
void func(int & a)
{
a = a * 3;
}
};
class C
{
protected:
void func(int & a)
{
a = a * 5;
}
};
class D : public A,public B,public C {
public:
int a;
A a_val;
B b_val;
C c_val;
void update_val(int new_val)
{
a = new_val;
a_val.func(a);
b_val.func(a);
c_val.func(a);
}
void check(int);
};
void D::check(int new_val)
{
update_val(new_val);
cout << "Value = " << a << endl;
};
int main()
{
D d;
int new_val;
cin >> new_val;
d.check(new_val);
}
If you want to keep your code with the base classes as having independent functionality and still remaining protected the easiest way to resolve your issue is by slightly changing the name of your protected functions and adding a public function that calls the protected members: See these class declarations for example:
class A {
public:
void func( int& a ) {
func_impl( a );
}
protected:
void func_impl( int& a ) {
a = a * 2;
}
};
class B {
public:
void func( int& b ) {
func_impl( b );
}
protected:
void func_impl( int& b ) {
b = b * 3;
}
};
class C {
public:
void func( int& c ) {
func_impl( c );
}
protected:
void func_impl( int& c ) {
c = c * 5;
}
};
class D : public A, public B, public C {
public:
int a;
A a_val;
B b_val;
C c_val;
void update_val( int val ) {
a = val;
a_val.func( a );
b_val.func( a );
c_val.func( a );
}
void check( int );
};
void D::check( int val ) {
update_val( val );
std::cout << "Value = " << a << std::endl;
}
This provides a nice public interface to call the protected member functions. This also resolves the issue of accessing the protected members. When I run your program and input a value of 5 it returns a result of 150 and works as expected.
This snippet should show you how inheritance works and when you can and can not access protected members:
class DerivedA : public Base {
public:
Base b;
void call_message() {
b.message(); // Protected Member of Base class can not be accessed
}
};
class DerivedB : public Base {
public:
void call_message() {
message(); // This works without problem!
}
};
Just as I did above one way to resolve this is by adding a public interface caller to the protected implementation.
class Base {
public:
void message() {
message_impl();
}
protected:
void message_impl() {
std::cout << "This is a protected member of Base\n";
}
};
Now you can do this:
class DerivedA {
public:
Base b;
void call_message() {
b.message(); // Accessible through public interface.
}
};
When you are in your derived class, it has access to its own ancestor methods. But it doesn't have access to your variables member protected and private methods and variables.
Redesign your code, you are trying things and contorting the other classes design for bad reasons. Francis' code is a good solution, but D doesn't need to inherit from anything.
If you don't want to create another function, you can do something like this:
#include <iostream>
using namespace std;
class A
{
protected:
void func(int & a)
{
a = a * 2;
}
};
class B
{
protected:
void func(int & a)
{
a = a * 3;
}
};
class C
{
protected:
void func(int & a)
{
a = a * 5;
}
};
class D : public A,public B,public C {
public:
int a;
void update_val(int new_val)
{
a = new_val;
this->A::func(a);
this->B::func(a);
this->C::func(a);
}
void check(int);
};
void D::check(int new_val)
{
update_val(new_val);
cout << "Value = " << a << endl;
};
int main()
{
D d;
int new_val;
cin >> new_val;
d.check(new_val);
}
This works because, this refers to the current instance of class D, and it already inherits class A, class B, class C. So you can directly access the protected functions of the respective classes.
Remember: It will not work if you have not inherited the classes.
I would like to create an hierarchy of classes in c++ so public variables of higher level classes were visible within lower level classes. Here is an example, the desired action is in "printf" of two constructors. As is now, variable a cannot be seen within class Local1. How to fix it? In general, classes will be defined in different files. Thank you.
class Global
{
int a;
Local1 l1;
}
class Local1
{
int b;
Local2 l2;
Local1(){printf("%i", a);}; #constructor
}
class Local2
{
Local2(){printf("%i, %i", a, b);}; #constructor
}
main()
{
Global g;
# want to create objects g, l1, l2, and print values of a and a,b
}
You could use inheritance.
Local2 inherits from Local1.
Local1 inherits from Global.
class Global
{
public:
int getA() {
return a;
}
virtual void doStuff() {
// do stuff
}
private:
int a;
};
class Local1 : public Global
{
public:
Local1(){
printf("%i", getA());
}
int getB() {
return b;
}
private:
int b;
};
class Local2 : public Local1
{
public:
Local2(){
printf("%i, %i", getA(), getB());
}
virtual void doStuff() override {
// do specific stuff
}
};
int _tmain(int argc, _TCHAR* argv[])
{
auto g = std::unique_ptr<Global>(new Local2());
g->doStuff(); // will call Local2::doStuff
}
Can't you simply pass to the child a pointer to the parent, like in the following naïve example?
#include<memory>
#include<iostream>
struct P {
struct C {
C(P *parent): p{parent} { }
void foo() {
std::cout << p->i << std::endl;
}
P *p;
};
int i;
C c{this};
};
int main() {
P p;
p.i = 42;
p.c.foo();
}
I have a problem with inheritance in C++. The attached code produces the output "1,1," but I thought the action methods from the classes b and c replace the action method from class a. So I expected the output "2,3,". What do I have to change to get the output "2,3,"?
#include <iostream>
//Class a
class a
{
public:
a();
int action();
};
a::a()
{
}
int a::action()
{
return 1;
}
//Class b
class b : public a
{
public:
b();
int action();
};
b::b()
{
}
int b::action()
{
return 2;
}
//Class c
class c : public a
{
public:
c();
int action();
};
c::c()
{
}
int c::action()
{
return 3;
}
//Main Programm
int main()
{
a arr[2];
arr[0] = b();
arr[1] = c();
for(int i = 0; i<2; i++)
{
std::cout << arr[0].action() << ",";
}
return 0;
}
Action needs to be virtual in the base class, otherwise you can't override it.
You can use the foo() override notation to get a compile-time check as to whether you're really overriding something.
You will have to access the derived type trough a pointer to the base type, otherwise you'll slice and do other nasty things. Also sometimes it's a good idea to also make your destructor virtual.
class Base { };
class Derived : public Base { };
some_container<Base*> baseOrDerived;
Then you can allocate both Base and Derived objects into this container. For example with new, although you probably want to use std::shared_ptr<Base> or std::unique_ptr<Base> instead of Base*.
you can use virtual function to get the output "2,3":
first, you should change void action(); to virtual void action(); in class a;
second, you should use pointer to implement polymorphism;
third, you should change arr[0] to arr[i];
Here is my code:
#include <iostream>
//Class a
class a
{
public:
a();
virtual int action();
};
a::a()
{
}
int a::action()
{
return 1;
}
//Class b
class b : public a
{
public:
b();
int action();
};
b::b()
{
}
int b::action()
{
return 2;
}
//Class c
class c : public a
{
public:
c();
int action();
};
c::c()
{
}
int c::action()
{
return 3;
}
int main(int argc, char *argv[])
{
a *(arr[2]);
arr[0] = new b();
arr[1] = new c();
for(int i = 0; i<2; i++)
{
std::cout << arr[i]->action() << ",";
}
return 0;
}
Here is my output:
I am trying to do something like this with c++.
void showContensofArray(void *data[])
{
//In this function have to display the values of respective objects.
// Any ideas how do I do it?
}
int main(){
A phew(xxx,abcdefg); //object of class A
B ball(90),ball2(88); //object of class B
void *dataArray[2];
dataArray[0] = &ph1;
dataArray[1] = &ball;
showContentsofArray(dataArray); //function
}
If you want to treat the objects in the data[] generically (i.e by calling a common function on them to extract a description or values) then define a class hirachy for your objects and in your showContentsofArray function call virtual methods on your (common base class) object pointers.
This is a textbook example of Polymorphism:
"polymorphism allows values of different data types to be handled using a uniform interface."
In the example below the base class BaseObject defines the uniform interface.
class BaseObject {
virtual string description() { return "Base object"; }
virtual bool bounces() { return false; }
}
class B : public BaseObject {
string description() { return "Im a B object" }
bool bounces() { return true; }
}
class A : public BaseObject {
string description() { return "Im an A object" }
}
void showContensofArray(BaseObject* data[], int size) {
for (int i=0; i<size; i++) {
cout << data[i]->description();
if (data[i]->bounces())
cout << "I bounce!";
}
}
int main() {
A phew(xxx,abcdefg); //object of class A
B ball(90),ball2(88); //object of class B
BaseObject* dataArray[2];
dataArray[0] = &ph1;
dataArray[1] = &ball;
showContentsofArray(dataArray);
}
Will output:
Im an A object
Im a B object
I bounce!
void showContensofArray(void *data[], int len)
{
int i;
for(i=0;i<len;i++){
((Base*)(data[i]))->print();
}
}
And every Class should have an implementation of the method print() that knows how to print its values.
You could also use inheritance.
EDIT:
#Ricibob's answer is correct, but if you need to do the casting inside the function, you need to do something like this:
#include <iostream>
using namespace std;
class Base{
public:
virtual void print()=0;
};
class A: public Base{
public:
void print(){
cout<<"Object A"<<endl;
}
};
class B: public Base{
public:
void print(){
cout<<"Object B"<<endl;
}
};
void showContensofArray(void* data[], int len)
{
int i;
for(i=0;i<len;i++){
((Base*)(data[i]))->print();
}
}
int main(){
A a;
B b;
void* v[2];
v[0]= &a;
v[1] = &b;
showContensofArray(v,2);
return 0;
}
You can't evade inheritance.
Just cast back to the original type:
A* p1 = static_cast<A*>(data[0]);
B* p2 = static_cast<B*>(data[1]);