I have 2 classes such as below:
class A : public C
{
void Init();
};
class B : public C
{
int a = 3;
};
How can i access the member of class B in class A?
class A::Init()
{
class B. a ???
}
Perhaps you want a static member, which you can access without an object of type B?
class B : public C
{
public:
static const int a = 3;
};
Now you can access it from anywhere (including your A::Init function) as B::a.
If that's not what you want, then please clarify the question.
You must create an instance of the class B and declare the variable public
class B : public C
{
public:
int a=3;//Data member initializer is not allowed in Visual Studio 2012, only the newest GCC
};
void A::Init()
{
B b;
b.a= 0;
}
If you don't want to create an instance of class B, declare the variable static
class B : public C
{
public:
static int a = 3;
};
And then access it like this:
void A::Init()
{
B::a=0;
}
if you want access a "property" of class B as global, not a particular object then make variable static in this class
class B : public C
{
public:
static const int a = 0;
};
and access it using B::a
alternatively:
class A{
public:
void init(){
static int a2 = 0;
a1=a2;
}
int a(){return a1;}
private:
static int a1;
};
int A::a1=0;
You can also try to add static function in your class. But I'm not sure if this what you
are looking for.
class B: public C
{
public:
static int GetA(void) {return a;}
private:
static int a;
};
int B::a = 4;
class A: public C
{
public:
void Init()
{
std::cout<<"Val of A "<<B::GetA()<<std::endl;
}
private:
int b;
};
Related
After some searching I've yet to find an existing question which address this issue. My apologies if I missed something.
I have a base class with a params structure and setter. I would like to redefine what that params structure looks like in a derived class and set it via a base class pointer. Something like the following for example.
class A
{
public:
struct paramsType
{
int a;
int b;
};
protected:
paramsType params;
public:
void setParams(const paramsType& params) { this->params = params; }
};
class B : public A
{
public:
struct paramsType
{
int c;
int d;
int e;
};
};
class C : public A
{
public:
struct paramsType
{
int f;
};
};
int main () {
A* ptrB = new B();
A* ptrC = new C();
B::paramsType paramsB;
paramsB.c = 0;
paramsB.d = 1;
paramsB.e = 2;
C::paramsType paramsC;
paramsC.f = 3;
ptrB->setParams(paramsB);
ptrC->setParams(paramsC);
delete ptrB;
delete ptrC;
}
I've tried making the base class "setParams" virtual and redefining it in the derived class, however when I call the method via the base class pointer, it has incompatible types.
In the real use case B and C share a ton of functionality which is implemented in A. They just have different parameter sets. I only have access to a base class pointer, but will know if the object is a B or a C. Is there an elegant way to address this?
Thanks!
You can't redefine a type but what you can do is a have a common base class for the parameters.
So you could make A::paramsType a base class and derive B::paramsType and C::paramsType from that. Then store a pointer to A::paramsType in class A. That way you can use a common base class for passing in the parameters.
However, in order to access members of B::paramsType and C::paramsType you'll need to cast down the inheritance hierarchy. You could implement that in a member function. If B::paramsType is derived from A::paramsType, it will be able to access all public and protected members of A::paramsType; likewise for C::paramsType.
It will be like this:
class A
{
public:
struct paramsType
{
virtual ~paramsType() = default;
int a;
int b;
};
protected:
std::unique_ptr<paramsType> params;
public:
void setParams(std::unique_ptr<paramsType> params) { this->params = std::move(params); }
};
class B : public A
{
public:
struct paramsType : A::paramsType
{
int c;
int d;
int e;
};
private:
B::paramsType* getParams() { return dynamic_cast<B::paramsType*>(params.get()); }
};
A working version here.
In your example, just change A to
class A
{
public:
struct paramsType
{
int a;
int b;
int c;
};
protected:
paramsType params;
public:
void setParams(const paramsType& params) { this->params = params; }
};
Then A can use paramsType::a and b while C can just ignore paramsType::b and c.
The program below fails, obviously, in the return expression:
#include <memory>
class Base {
public:
class Nested {
public:
int c;
};
};
class A : public Base {
public:
class Nested : public Base::Nested {
public:
int c = 1;
};
};
class B : public Base {
public:
class Nested : public Base::Nested {
public:
int c = 2;
};
};
int main() {
std::shared_ptr<Base> X = std::make_shared<A>();
return X::Nested.c;
};
How can I get Nested.c value of X?
In other words, I have one base class (Base) and two derived classes (A and B). Each derived class has a nested class (Nested). I want to called Nested.c from an instance X, which is dynamically selected as one of the derived classes.
Probably just a misconception about nested classes. A Nested class does not magically add members to it's parent class. You need to do that manually, for example:
class Base {
public:
class Nested {
public:
int c;
};
Nested nested; // member of nested class Base::Nested.
};
Keep in mind that Base::Nested, A::Nested and B::Nested are all different classes. Allthough they look similiar they are not related at all.
Maybe the following is what you want:
#include <memory>
class Base {
private:
class Nested {
public:
int c;
};
Nested nested; // member of nested class Base::Nested.
public:
virtual int getC() const { return this->nested.c; }
};
class A : public Base {
private:
class Nested {
public:
int c = 1;
};
Nested nested; // member of nested class A::Nested.
public:
int getC() const override { return this->nested.c; }
};
class B : public Base {
private:
class Nested {
public:
int c = 2;
};
Nested nested; // member of nested class B::Nested.
public:
int getC() const override { return this->nested.c; }
};
int main() {
std::shared_ptr<Base> X = std::make_shared<B>();
return (*X).getC();
};
Each class has it's own member of it's own nested class and returns c with a virtual getter.
Simply, I need to do as the title says: Call a child static method from parent. The problem is that I don't know the child class name in the parent as there could be multiple children. The static method needs to stay static. For example:
class A{ // parent class
public:
void process(){
getData(); // <-- Problem
}
}
class B: public A{ // child class
static int getData();
}
void main(){
B b;
b.process();
}
One solution that comes to mind is to have a virtual method that calls the static method. This would not be very nice and it would mean I would have to implement the method for every child I have:
class A{ // parent class
virtual int getDataFromStaticMethod() = 0;
public:
void process(){
getData(); // <-- Problem
}
}
class B: public A{ // child class
static int getData();
virtual int getDataFromStaticMethod(){
return B::getData();
}
}
void main(){
B b;
b.process();
}
But I really wish it was possible to implement a pure virtual method with a static method:
class A{ // parent class
virtual int getData() = 0;
public:
void process(){
getData(); // <-- Problem
}
}
class B: public A{ // child class
static int getData();
}
void main(){
B b;
b.process();
}
Any suggestions?
Thanks!
You could use templates.
template<typename TChild>
class A
{
typedef TChild child_type;
public:
void process()
{
child_type::getData();
}
};
class B: public A<B>
{
static int getData();
};
class C: public A<C>
{
static int getData();
};
int main(int argc, char** argv)
{
B b;
b.process();
C c;
c.process();
}
Note:
If you want to hold static state in your base class, or if you need to hold a collection of base class objects, then you would need an additional layer:
class ABase
{
//any static state goes here
public:
virtual int process() = 0;
};
template<typename TChild>
class A: public ABase
{
typedef TChild child_type;
public:
int process()
{
child_type::getData();
}
};
class B: public A<B>
{};
std::vector<ABase*> a_list;
Assuming the signature of the child functions are all identical, you could initialize your base class object to hold a pointer to the child's version of the getData() function, e.g.:
class A {
int (*d_getData)();
protected:
explicit A(int (*getData)()): d_getData(getData) {}
public:
void process() {
int data = (this->d_getData)();
// ...
}
};
Obviously, the child classes would need to provide the corresponding constructor argument:
class B: public A {
static int whatever();
public:
B(): A(&whatever) {}
// ...
};
That's sort of an implementation of a per object overridable virtual function.
You can use virtual wrappers around the static function. E.g.
class A{ // parent class
// don't make pure virtual if you don't want to define it in all child classes
virtual int getData() { return 0 };
public:
void process(){
getData();
}
}
class B: public a{ // child class
static int do_getData();
int getData() { return do_getData(); }
}
class A{
int _a;
public:
/--/ void setfunc(int a) ............. will static works here
{
_a=a;
}
int getValue(){return _a};
};
class B{
public:
void func()
{
/--/ setfunc(1); ...................Dont want to create object of A.
}
};
class C{
public:
void something()
{
A aa;
cout<<aa.getValue(); ............. want a value update by class B setfunc
}
};
int main()
{
B bb;
bb.func();
C cc;
cc.something();
}
Question : How can setfunc() can be called in another function without using that class object. Also, if it changes like setting value of "_a" via someclass B. the same value of will persist whenever I try to retrieve it in someanother class like C via getValue()
In static function you can use only static members of class. Like this (_a is static):
class A {
static int _a;
public:
static void setfunc(int a)
{
_a=a;
}
static int getValue(){return _a};
};
Otherwise, you can't do anything with non-static members:
class A {
int _a;
public:
static void setfunc(int a)
{
_a=a; // Error!
}
static int getValue(){return _a}; // Error!
};
I have a class as follows:
Class A
{
virtual int doSomethingCool() = 0;
};
Class B : public A
{
int doSomethingCool();
};
Now the problem likes , I have a set of classes whcih are dependent on A as interface. I need to change the prototype of the function for one of the derived classes. i.e. i need to pass it a parameter.
Class C: public A
{
int doSomethingCool(int param);
};
Any suggestions how i can achieve this ?
No, you don't need to add it to the base class.
class A
{
public:
virtual int doSomethingCool() = 0 {}
};
class B : public A
{
public:
int doSomethingCool() {return 0;}
};
class C: public A
{
private:
int doSomethingCool(); // hide base class version!
public:
int doSomethingCool(int param) {return param;}
};
You can still call doSomethingCool() if done through a base class pointer:
C c;
//c.doSomethingCool (); // doesn't work, can't access private member
c.doSomethingCool (42);
A &a = c;
a.doSomethingCool ();
//a.doSomethingCool (42); // doesn't work, no member of A has that signature
Add it to the interface and default it to call the existing method. You don't have to do the default but don't make it pure otherwise all derived classes will have to implement. It might be better to leave it undefined or to throw. Depends on what you want to achieve.
class A
{
public:
virtual int doSomethingCool() = 0;
virtual int doSomethingCool(int param) {doSomethingCool()};
};
Make the function doSomethingCool() take the int parameter in A.
class A
{
public:
virtual void doSomethingCool(int param) = 0;
};
There's no problem. You can do it. The only caveat is that it will not be treated as an override of the base class virtual function.
class A
{
public:
virtual void doSomethingCool() = 0;
};
class B : public A
{
public:
void doSomethingCool();
};
class C: Public A
{
public:
void doSomethingCool(int param);
};
int main(){}
So while technically possible, you may really want to relook at the design of your interface class A.
One option may be to provide a default argument to A::doSomethingCool
virtual void doSomethingCool(int = 0) = 0;
This isn't syntactically correct C++.
No you can't change a prototype. How would it be used? What would be the value of the param if the non-parametric version would be called?
I would have introduced another, more specific, interface:
struct A
{
virtual int doSomethingCool() = 0;
};
struct A_specific : A
{
virtual int doSomethingCoolWithThis(int i) = 0;
};
class ConcreteA : public A
{
int doSomethingCool() { return 0; }
};
class ConcreteA_specific : public A_specific
{
int doSomethingCool() { return 0; }
int doSomethingCoolWithThis(int param) { return param; }
};
Then I would program to the correct interface:
int main()
{
const A& a1 = ConcreteA();
const A_specific& a2 = ConcreteA_specific();
a1.doSomethingCool();
a2.doSomethingCool();
a2.doSomethingCoolWithThis(2);
}
Just to give you another idea ;-)
Good luck!