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.
Related
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...
}
#include <iostream>
using namespace std;
class ParentClass
{
public:
int id;
ParentClass(int id)
{
this->id = id;
}
void print()
{
cout << id << endl;
}
};
class ChildClass: public ParentClass
{
public:
int id;
ChildClass(int id): ParentClass(1)
{
this->id = id;
}
};
int main()
{
ChildClass c(2);
c.print();
return 0;
}
I run this C++ file and I get '1' as output, I want to know how should I write to get '2' as output ? Or say that how to access a redefined variable from a derived class.
You cannot access ChildClass::id from ParentClass::print. More generally: You cannot access members of a derived class, from a member function of the parent.
You can access ChildClass::id within the member functions of ChildClass.
ChildClass::id isn't a "redefined" variable. It is a separate, unrelated variable that happens to have the same identifier, but in different scope. There is no concept of "redefining" a member variable in a derived class, in C++.
I recommend considering, whether it makes sense for ChildClass to have two different ids.
Your ChildClass is doing some wrong or discutable stuff:
1. it's "shadowing" the int id member of ParentClass
2. it's calling the ParentClass constructor passing 1 (instead of "id")
3. it's using assignements in constructors instead of initializer lists
4. ParentClass::id visibility may be decreased from public to protected or private.
Try the following modified code:
#include <iostream>
class ParentClass
{
public:
int id;
ParentClass(int id) : id(id) {}
void print()
{
std::cout << id << std::endl;
}
};
class ChildClass: public ParentClass
{
public:
ChildClass(int id): ParentClass(id) {}
};
int main()
{
ChildClass c(2);
c.print();
return 0;
}
I haven't worked with derived classes and polymorphism in a while, and I can't figure out how to access a derived class data item.
// Quick example
class Base {
string data1; // data1 = "FOO"
};
class ChildA : public Base {
string data2;
};
int main() {
Base **list;
list = new Base*[1];
base[0] = new ChildA(// data2 = "BAR");
std::cout << base[0]->data1; // FOO
std::cout << base[0]->data2; // Error; no member named "data2" in Base
Is it possible to retrieve the derived data from the base class array?
When you're looking at an instance of a derived class through a pointer to the base class, you can only see the members of the base class, because generally, you wouldn't know what subtype instance you are looking at. The point of polymorphism and virtual functions is that in many cases, you can work with subtype instances without knowing their actual type. For instance, if you want to print information about an instance, and you want data2 to be included when you print a ChildA, you would create a virtual toString() function in Base and override it in ChildA to include data2. Then, you can call toString() without knowing the actual type, and if your instance is actually a ChildA, you'll get data2.
class member variable by default is private.
by using base class pointer, you can not get derived class member var at all.
If you would like to do so, you may want to implement virtual getter function, it will help you getting private member function from derived class.
If the base class interface must have knowledge of data potentially held in a derived class, here is one of the few ways that is not horribly dangerous.
#include <iostream>
#include <vector>
#include <utility>
#include <memory>
#include <stdexcept>
using namespace std;
class Base {
public:
Base(std::string d1 = {"FOO"} ) : _data1 { std::move(d1) } {}
virtual ~Base() = default; // because polymorphism without a virtual base class is naughty
const string& data1() const { return _data1; }
virtual bool has_data2() const { return false; }
virtual const string& data2() const {
throw invalid_argument {"I don't have data2"};
};
private:
string _data1; // data1 = "FOO"
};
class ChildA : public Base {
public:
ChildA(std::string d2, std::string d1 = {"FOO"})
: Base { std::move(d1) }
, _data2 { std::move(d2) }
{}
bool has_data2() const override { return true; }
const std::string& data2() const override {
return _data2;
};
private:
string _data2;
};
int main()
{
vector<unique_ptr<Base>> bases;
bases.push_back(unique_ptr<Base>(new ChildA("bob")));
bases.push_back(unique_ptr<Base>(new Base("not foo")));
for(const auto& p : bases) {
cout << p->data1() << ", " << (p->has_data2() ? p->data2() : "no data 2") << endl;
}
return 0;
}
Let's say we have a derived class from an abstract base class. A pointer to the abstract base class is declared in the main and allocated to the derived class through "new". How do you access the member functions of the derived class from a pointer to the base class (not from an object of the derived class)?
Example:
#include <iostream>
using namespace std;
class clsStudent
{
public:
virtual void display() = 0;// {cout<<"Student\n";}
};
class clsInternational : public clsStudent
{
public:
void display(){cout<<"International\n";}
void passportNo(){cout<<"Pass\n";}
};
class local : public clsStudent
{
public:
void display(){cout<<"International\n";}
void icNo(){cout<<"IC\n";}
};
int main()
{
clsStudent * s = new clsInternational;
clsStudent * s2 = new local;
s->display();
s->passportNo(); //This won't work
return 0;
}
Cheeky answer: don't. I mean, if you really need to, the answer to your technical question is the dynamic_cast operation in C++, in order to a conduct a "downcast" (cast from base to derived class).
But stepping back, this is a reasonable use case for a virtual function. Ask yourself, what is the common meaning I want to access?
In this case, we want all students to have an identifying number.
Working source code: http://ideone.com/5E9d5I
class clsStudent
{
public:
virtual void display() = 0;// {cout<<"Student\n";}
virtual void identifyingNumber() = 0;
};
class clsInternational : public clsStudent
{
public:
void display(){cout<<"International\n";}
void identifyingNumber(){cout<<"Pass\n";}
};
class local : public clsStudent
{
public:
void display(){cout<<"Local\n";}
void identifyingNumber(){cout<<"IC\n";}
};
int main()
{
clsStudent * s = new clsInternational;
clsStudent * s2 = new local;
s->display();
s->identifyingNumber();
s2->display();
s2->identifyingNumber();
return 0;
}
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.