I recently asked a question related to the accessibility of a child member from a parent class using the cout method . But this time what if I want to use a get method instead of cout ? Will this change the idea ?
Assuming I have a class called CArray :
class CArray
{
public:
CArray();
private:
std::vector<CPerson *>Persons;
};
Where CPerson a parent class :
class CPerson
{
public:
CPerson();
virtual void Print()
{
std::cout << Name << "\n";
}
protected:
std::string Name;
};
and CStudent the child of Person
class CStudent : public CPerson
{
public:
CStudent();
private:
int MatriculationNr;
};
Let's assume that we loaded the private members of CStudent and CPerson as follows :
if (condition)
{
CStudent *S1 = new CStudent();
S1->load(src); //Load function is missing in class but ignore it
Persons.push_back(S1);
}
I recently learned how to access the private member of CStudent and CPerson with the use of the virtual method and exactly by adding to CStudent class this function below :
void Print()
{
CPerson::Print();
std::cout << MatriculationNr << "\n";
}
Now moving on to my class CArray . I wrote a print method to print the elements of Persons :
I just have to write Persons[i]->Print(); which will call Print() from all Persons .
The question now what If I want to get the MatriculationNr from the first element of Persons (as an example)?
cout << Persons[i]->getMatrikulNr();is not valid since we're trying here to get a function from a child class which is not possible this way .
I wanted to apply the same behavior that I did with print() but this is not possible due to the return parameter that I will have with the get method .
what If I want to get the MatriculationNr from the first element of Persons (as an example)?
You won't be able to. Not with the code you have shown, anyway. MatriculationNr exists only in CStudent, and it is private at that, so only CStudent can access it.
cout << Persons[i]->getMatrikulNr(); is not valid since we're trying here to get a function from a child class which is not possible this way . I wanted to apply the same behavior that I did with print() but this is not possible due to the return paramater that I will have with the get method .
You would have to either:
add a public virtual getMatrikulNr() method to CPerson which CStudent can then override, eg:
class CPerson
{
public:
...
virtual int getMatrikulNr() const
{
return 0;
}
...
};
class CStudent : public CPerson
{
public:
...
int getMatrikulNr() const override
{
return MatriculationNr;
}
private:
int MatriculationNr;
};
And then you can use Persons[i]->getMatrikulNr() as needed.
add a public getMatrikulNr() method to CStudent, and then dynamic_cast each CPerson* pointer to see if it is pointing at a CStudent object or not, eg:
class CStudent : public CPerson
{
public:
...
int getMatrikulNr() const
{
return MatriculationNr;
}
private:
int MatriculationNr;
};
CStudent *student = dynamic_cast<CStudent*>(Persons[i]);
if (student) {
// use student->getMatrikulNr() as needed...
}
Related
The question extends this question
The situation is the following. I'm extending a virtual method of a inner class:
class ClassOne {
public:
class InnerClass {
public:
virtual void method1();
protected:
friend class ClassOne
};
protected:
oftenUsedMethod();
private:
friend class InnerClass;
};
void ClassOne::InnerClass::method1()
{
#Do stuff with oftenUsedMethod();
}
class SubClassOne : public ClassOne {
class DerivedInnerClass : InnerClass {
virtual void method1();
};
};
void SubClassOne::DerivedInnerClass::method1()
{
##I need the access to the oftenUsedMethod???
}
Here is an image to try to clarify the problem :)
InnerClass uses ofthenUsedMethod() in its methods, and has access to it. To be able to extend the methods, I need access to ofthenUsedMethod() in DerivedInnerClass. Can this be achieved?
There are two problems to overcome:
Inner classes, by default, are not associated with an instance of the outer class, sou you'll have to make this dependency explicit by giving it a pointer to the outer class. If you do this, you'll need to be careful that instances of the inner class don't outlive the object they are referring to.
The derived inner class is not derived from the outer class so it does not have access to its protected members. What you can do is add a protected function into InnerClass that calls the function. This function is a member of InnerClass and derived classes can call it. Dynamic binding will do the rest.
Here is the above in C++:
#include <iostream>
class ClassOne
{
protected:
virtual void
oftenUsedMethod()
{
std::clog << "ClassOne::oftenUsedMethod()" << std::endl;
}
class InnerClass
{
private:
/** Pointer to an instance of the outer class. */
ClassOne *const outer_;
public:
InnerClass(ClassOne *const outer) : outer_ {outer}
{
}
protected:
virtual void
method1()
{
std::clog << "ClassOne::InnerClass::method1()" << std::endl;
this->dispatch();
}
/**
* Simply calls the protected member of the outer class.
* Derived classes can therefore access it indirectly, too.
*
*/
void
dispatch()
{
// Be aware: If *this->outer_ has already been destructed
// (and there is no simple way for us to tell whether it has),
// calling a member function on it will cause disaster.
this->outer_->oftenUsedMethod();
}
};
};
class SubClassOne : public ClassOne
{
protected:
virtual void
oftenUsedMethod() override
{
std::clog << "SubClassOne::oftenUsedMethod()" << std::endl;
}
class DerivedInnerClass : public ClassOne::InnerClass
{
DerivedInnerClass(ClassOne *const outer) : InnerClass {outer}
{
}
protected:
virtual void
method1() override
{
std::clog << "SubClassOne::DerivedInnerClass::method1()" << std::endl;
this->dispatch();
}
};
};
The override is a C++11 feature, you don't need it but it makes your intention clear.
Consider this pseudocode:
class Foo {
public:
virtual int getID() const = 0;
}
template<typename T>
class Blah : public Foo {
public:
T data;
static const int ID; //static ID
int getID() const { return Blah<T>::ID; } //instance returns the ID
}
class Dude : public Blah<int> {
}
int Dude::ID = 10; //I want to define Blah<int>::ID here, but how?
int receive(const Foo& foo) {
if(foo.getID() == Dude::ID) {
cout << "Received a Dude" << endl;
}
}
This piece of code fails to compile because ISO C++ does not permit the ID in the Blah template to be defined as the ID in the Dude class. I understand why because I could have multiple classes that extend a Blah<int>.
I understand if I put template<typename T> int Blah<T>::ID = 10' in the Blah<T> impl that it will work...but that isn't what I want...I want the derived class to define the ID...
Do I have to push the ID and getID() into the derived class? I guess ultimately I'm interested in some RTTI so I can process the Foo appropriately. If anyone has a better pattern, I'm all ears.
EDIT
In response to some of the comments...I would like to uniquely identify classes that derive from Foo via some ID so I can compare the runtime id of some Foo object to a specific class id.
Thanks!
Make the static int ID; private, and provide GetID in public interface, make SetID a protected interface. But that is not a good solution, because all the derived class will share the same ID, which is not what you want.
A better way should be you use the id as the base class' template parameter, then class Derived : public Base<234>{} will work.
Or add virtual const int GetID() = 0 into Base class.
I think you can simply do this:
class Dude : public Blah<int> {
}
static const int Dude_ID; //declaration!
int receive(const Foo& foo) {
if(foo.getID() == Dude::Dude_ID) {
cout << "Received a Dude" << endl;
}
}
static const int Dude::Dude_ID = 10; // definition!
Similarly, define an ID for each derived class.
Yet another way to have an ID for each class is this:
template<typename T, int ID=1>
class Blah : public Foo {
public:
int getID() const { return ID; }
}
template<int ID=10>
class Dude : public Blah<int> {
public:
int getID() const { return ID; }
}
I found this answer that does exactly what I'm after...sorry if my question was confusing.
in C++, how to use a singleton to ensure that each class has a unique integral ID?
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.
when we say "a member declated as protected is accessible to any class imediately derived from it" what does this mean.
in the follwing example get_number function can be accessible by the result class , as per the statement it sould only be accessile to test class.
class student
{
protected:
int roll_number;
public:
void get_number(int){ cout<< "hello"; }
void put_number(void) {cout<< "hello"; }
};
class test : public student
{
protected:
float sub1;
float sub2;
public:
void get_marks(float, float) {cout<< "hello"; roll_number = 10; }
void put_marks(void) {cout<< "hello"; cout << "roll_number = " << roll_number ; }
};
class result : public test
{
float total;
public:
void display(){cout<< "hello"; roll_number = 10; }
};
int main()
{
result student;
student.get_marks(2.2, 2.2);
student.put_marks();
return 0;
}
i changed the code as per the first statement the protected variable roll_number not be accessible upto the result class ?
You have declared get_number as public so all classes can see it.
If you want class result to not have direct access to data member roll_number you need to change the inheritance access of class test to protected:
class test : protected student
{
};
For more information, see The C++ FAQ Lite: Public and Private Inheritance. Changing how class test inherits from class student also affects how data members in class student are accessed by classes derived from class test.
An alternative to inheritance is for class test to contain a private pointer to an instance of class student, as long as class student is not an abstract class.
Is there anyway to have a sort of virtual static member in C++?
For example:
class BaseClass {
public:
BaseClass(const string& name) : _name(name) {}
string GetName() const { return _name; }
virtual void UseClass() = 0;
private:
const string _name;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass("DerivedClass") {}
virtual void UseClass() { /* do something */ }
};
I know this example is trivial, but if I have a vector of complex data that is going to be always the same for all derived class but is needed to be accessed from base class methods?
class BaseClass {
public:
BaseClass() {}
virtual string GetName() const = 0;
virtual void UseClass() = 0;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() {}
virtual string GetName() const { return _name; }
virtual void UseClass() { /* do something */ }
private:
static const string _name;
};
string DerivedClass::_name = "DerivedClass";
This solution does not satify me because I need reimplement the member _name and its accessor GetName() in every class. In my case I have several members that follows _name behavior and tenths of derived classes.
Any idea?
Here is one solution:
struct BaseData
{
const string my_word;
const int my_number;
};
class Base
{
public:
Base(const BaseData* apBaseData)
{
mpBaseData = apBaseData;
}
const string getMyWord()
{
return mpBaseData->my_word;
}
int getMyNumber()
{
return mpBaseData->my_number;
}
private:
const BaseData* mpBaseData;
};
class Derived : public Base
{
public:
Derived() : Base(&sBaseData)
{
}
private:
static BaseData sBaseData;
}
BaseData Derived::BaseData = { "Foo", 42 };
It seems like the answer is in the question - the method you suggested seems to be the right direction to go, except that if you have a big number of those shared members you might want to gather them into a struct or class and past that as the argument to the constructor of the base class.
If you insist on having the "shared" members implemented as static members of the derived class, you might be able to auto-generate the code of the derived classes. XSLT is a great tool for auto-generating simple classes.
In general, the example doesn't show a need for "virtual static" members, because for purposes like these you don't actually need inheritance - instead you should use the base class and have it accept the appropriate values in the constructor - maybe creating a single instance of the arguments for each "sub-type" and passing a pointer to it to avoid duplication of the shared data. Another similar approach is to use templates and pass as the template argument a class that provides all the relevant values (this is commonly referred to as the "Policy" pattern).
To conclude - for the purpose of the original example, there is no need for such "virtual static" members. If you still think they are needed for the code you are writing, please try to elaborate and add more context.
Example of what I described above:
class BaseClass {
public:
BaseClass(const Descriptor& desc) : _desc(desc) {}
string GetName() const { return _desc.name; }
int GetId() const { return _desc.Id; }
X GetX() connst { return _desc.X; }
virtual void UseClass() = 0;
private:
const Descriptor _desc;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(Descriptor("abc", 1,...)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass("Wowzer", 843,...) {}
virtual void UseClass() { /* do something */ }
};
I'd like to elaborate on this solution, and maybe give a solution to the de-initialization problem:
With a small change, you can implement the design described above without necessarily create a new instance of the "descriptor" for each instance of a derived class.
You can create a singleton object, DescriptorMap, that will hold the single instance of each descriptor, and use it when constructing the derived objects like so:
enum InstanceType {
Yellow,
Big,
BananaHammoc
}
class DescriptorsMap{
public:
static Descriptor* GetDescriptor(InstanceType type) {
if ( _instance.Get() == null) {
_instance.reset(new DescriptorsMap());
}
return _instance.Get()-> _descriptors[type];
}
private:
DescriptorsMap() {
descriptors[Yellow] = new Descriptor("Yellow", 42, ...);
descriptors[Big] = new Descriptor("InJapan", 17, ...)
...
}
~DescriptorsMap() {
/*Delete all the descriptors from the map*/
}
static autoptr<DescriptorsMap> _instance;
map<InstanceType, Descriptor*> _descriptors;
}
Now we can do this:
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.BananaHammoc)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.Yellow)) {}
virtual void UseClass() { /* do something */ }
};
At the end of execution, when the C runtime performs uninitializations, it also calls the destructor of static objects, including our autoptr, which in deletes our instance of the DescriptorsMap.
So now we have a single instance of each descriptor that is also being deleted at the end of execution.
Note that if the only purpose of the derived class is to supply the relevant "descriptor" data (i.e. as opposed to implementing virtual functions) then you should make do with making the base class non-abstract, and just creating an instance with the appropriate descriptor each time.
I agree with Hershi's suggestion to use a template as the "base class". From what you're describing, it sounds more like a use for templates rather then subclassing.
You could create a template as follows ( have not tried to compile this ):
template <typename T>
class Object
{
public:
Object( const T& newObject ) : yourObject(newObject) {} ;
T GetObject() const { return yourObject } ;
void SetObject( const T& newObject ) { yourObject = newObject } ;
protected:
const T yourObject ;
} ;
class SomeClassOne
{
public:
SomeClassOne( const std::vector& someData )
{
yourData.SetObject( someData ) ;
}
private:
Object<std::vector<int>> yourData ;
} ;
This will let you use the template class methods to modify the data as needed from within your custom classes that use the data and share the various aspects of the template class.
If you're intent on using inheritance, then you might have to resort to the "joys" of using a void* pointer in your BaseClass and dealing with casting, etc.
However, based on your explanation, it seems like you need templates and not inheritance.
#Hershi: the problem with that approach is that each instance of each derived class has a copy of the data, which may be expensive in some way.
Perhaps you could try something like this (I'm spit-balling without a compiling example, but the idea should be clear).
#include <iostream>
#include <string>
using namespace std;
struct DerivedData
{
DerivedData(const string & word, const int number) :
my_word(word), my_number(number) {}
const string my_word;
const int my_number;
};
class Base {
public:
Base() : m_data(0) {}
string getWord() const { return m_data->my_word; }
int getNumber() const { return m_data->my_number; }
protected:
DerivedData * m_data;
};
class Derived : public Base {
public:
Derived() : Base() {
if(Derived::s_data == 0) {
Derived::s_data = new DerivedData("abc", 1);
}
m_data = s_data;
}
private:
static DerivedData * s_data;
};
DerivedData * Derived::s_data = 0;
int main()
{
Base * p_b = new Derived();
cout getWord() << endl;
}
Regarding the follow-up question on deleting the static object: the only solution that comes to mind is to use a smart pointer, something like the Boost shared pointer.
It sounds as if you're trying to avoid having to duplicate the code at the leaf classes, so why not just derive an intermediate base class from the base class. this intermediate class can hold the static data, and have all your leaf classes derive from the intermediate base class. This presupposes that one static piece of data held over all the derived classes is desired, which seems so from your example.