below is the small program.
i want to check the value of the private variable x of class A using the object of class B.
is it possible ever?
#include<stdio.h>
#include<conio.h>
#include<iostream>
class A {
int x;
public:
A() {
x=10;
}
};
class B : public A {
public:
int x;
};
int main()
{
B obj;
obj.x=20;
std::cout<< obj.x;
getch();
}
This will output 20, but how can i check the value of x as 10 which is in class A?
i wanted to know whether we can check the value without making x as protected!
You'll have to make the variable protected, or, you can create a protected member method in class A which returns the variable x.
By using the 2nd approach (protected member method or property (is that possible in C++?), class B can read the variable, but cannot change it.
Derived classes cannot see ancestor privates. You can use "protected" for descendents to see the data, but not unrelated classes.
In addition to the private / protected issue, your B::x member over-shades the x of A. So even if both were public, you'd have to write b.A::x. Looks weird, but works (see code below) ....
This is syntax-wise. You should tot do this, of course, as everybody here say. use protected members with meaningful names, and accessor functions
class A {
public:
int x;
};
class B: public A {
public:
int x;
void f() { std::cout << "B::x=" << x << ", A::x=" << A::x << '\n'; }
};
int main()
{
B b;
b.A::x = 10;
b.x = 20;
b.f();
}
output:
B::x=20, A::x=10
You can not examine the value of private members of base class. So: add an accessor in A or make A::x protected.
Make x in A protected and write a method in B that looks something like this:
int getAX(){
return A::x
}
You shouldn't.
Since your A class tells the member is private, nobody but A can access it.
If B is-an-A, the same rule is valid: A::x is still inaccessible.
Your wanting to access it means you either need a different kind of A (i.e. make A::x public), or you want the wrong thing.
Well, if you really want to know if it's possible: it is. public, protected and private are only compile time checks. One possible option to circumvent them during runtime is the following:
#include <iostream>
class A{
int x;
A() : x(10){}
};
struct pubA{
int x;
};
int main(){
A a;
// evil casting
pubA* pa = reinterpret_cast<A*>(&a);
std::cout << pa->x << std::endl; // should print 10
}
That said, don't do it. There is a reason for these keywords. (The above code is untested, 'caus I'm writing from my iPod. If reinterpret_cast doesn't work, use old C-style cast: pa = (pubA*)&a.)
Related
Lets say I have a class A that has a member of type int.
I have a class B which is a subclass of A.
B is meant to initialize the members to some state and has no other purpose.
#include <string>
#include <iostream>
struct A {
int someInt;
A() : someInt(33){}
};
struct B : public A {
B() {
someInt = 4;
}
};
int main() {
A a = A();
A b = B();
std::cout<< a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
Notice how I use A b = B() where object slicing should occur.
However since B doesn't add anything to A, is it a valid alternative to using A with different constructor parameters (or any other form of creating instances of A)?
Edit:
The background is that I have a class that has some complex setup.
Putting the initialization into separate child class is way easier than lets say write a constructor, factory or builder.
More common and less error prone method is to define static methods to create your class instances:
struct A {
static A makeA();
static A makeB();
};
int main()
{
auto a = A::makeA();
auto b = A::makeB();
}
and to prevent even more errors you may want to prohibit creation of instances of A directly, rather than set of static methods by making A ctor private.
To answer your question as directly as possible, what you're doing is certainly "valid" in the sense that it will compile and run and produce a correct result. It's probably not the most common way to accomplish this though.
My recommendation for a more idiomatic approach would be to use a common base class and templatize all of your derived versions. Basically make the compiler do the work of setting the integer value you want.
struct ABase {
int someInt;
ABase() = delete;
ABase(int initVal) : someInt(initVal) { }
};
template<int T>
struct A : public ABase {
A() : ABase(T) {}
};
int main() {
ABase a = A<33>();
ABase b = A<4>();
std::cout << a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
This is probably less code overall (especially if you have more than just two versions of this class), and much more flexible.
As a better practice,
Use another constructor in class A and this constructor will take parameters OR Use a separate function in class A to do what you want.
And regarding "Putting the initialization into separate child class is way easier than lets say write a constructor, factory or builder" doesn't make sense in this situation, so it's not easier even the code is complex as you said.
Please help me understand why it is possible for a class member function to return a private nested class object, and why it is then possible to call member functions on that private nested class, eg:
class Y
{
class X
{
public:
void f() { cout << "Hello World" << endl; }
};
public:
X g() { return X(); }
};
void h()
{
Y::X x; // Error, as expected: class Y::X is private.
x.f(); // Error.
Y y; // OK.
y.g().f(); // OK. But why???
}
I tested with GCC and Visual C++, and that last line compile on both. I cannot seem to find anything in the C++ standard that would make this valid. Any ideas why this works?
Edit:
Another observation:
void i()
{
Y y;
Y::X x2 = y.g(); // Error: class Y::X is private
x2.f(); // Error
auto x3 = y.g(); // OK
x3.f(); // OK
}
Making a nested class private doesn't mean external scopes can never use an instance of that class. Access specifiers affect names, and your main function never attempts to name Y::X.1 The only place where Y::X is named is within Y, which of course has access to its own private members. That the function returns an instance of Y::X to main isn't particularly relevant.
[C++14: 11/1]: A member of a class can be
private; that is, its name can be used only by members and friends of the class in which it is declared.
protected; that is, its name can be used only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see 11.4).
public; that is, its name can be used anywhere without access restriction.
Admittedly, the standard does not have any text to explicitly unconfuse you and point out that access to the entities themselves is not controlled by these keywords, but that is definitely the intent and, ultimately, as far as the legalese goes.
1 It does name Y::X::f, but that name is public.
why it is possible for a class member function to return a private nested class object
A nested class is a class member too, and the member function has the access right on the private member.
and why it is then possible to call member functions on that private nested class
You're not using the private nested class name here, i.e. Y::X. And Y::X::f() is a public function, so it's possible to call it directly.
Here you can find the example that you are looking for. f1 is public, f2 is private and triggers the error you are expecting:
#include <iostream>
class Y
{
class X
{
public:
void f1() { std::cout << "Hello World" << std::endl; }
private:
void f2() { std::cout << "Hello World" << std::endl; }
};
public:
X g() { return X(); }
};
int main()
{
// Y::X x; // Error, as expected: class Y::X is private.
// x.f(); // Error.
Y y; // OK.
y.g().f1(); // OK. Because f1 is public.
y.g().f2(); // Error. Because f2 is private.
return 0;
}
I am trying to understand inheritance and I need some help building two classes. The fist one is called A, the second one is called B.
A has one private integer value "m_a". It has two constructors, the default one sets m_a to 5. and another one which takes as an argument an integer called m and sets m_a's value to m. As for member functions it will have two. The first one will return m_a. The second one will print "Hello from A!". Let's move on to B. B will have a private string m_s. A default constructor which will set m_s to "asd" or to anything other than an empty string and a constructor which will take as an argument a string and set m_s to it's value. As far as functions go, firstly B will have a function that will return m_s. It will have a function which will have the same name as the print "Hello from A" function in A which will override it and it will printout "Hello from B!" instead (is that polymorphism ?).
Those are the classes needed. I have the following questions (I will post what I have created below)
Firstly, is there any way I can get to the private data fileds from the base class. For example let's say I want to take the m_s variable, add it to another one and print out their sum. Is that possible ? (and how)
Also when I try to create a class with a constructor different from the default one I get errors. I am obviously doing something wrong. The question is what.
I think those are all of my questions for now, so it is time for me to post the source code.
#include <iostream>
#include <string>
using namespace std;
class A
{
private:
int m_a;
public:
A(){m_a = 5;}
A(int m)
{
m_a = m;
}
void pm()
{
cout << "Hello from A!" << endl;
}
int get_a()
{
return m_a;
}
};
class B : A
{
private :
string m_s;
public:
B(){m_s = "asd";}
B(string s)
{
m_s = s;
}
void pm()
{
cout << "Hello from B!" << endl;
}
string get_s()
{
return m_s;
}
};
int main()
{
A a(10);
a.pm();
cout << a.get_a() << endl;
B b("asd");
b.pm();
cout << b.get_s() << endl;
cout << b.get_a() << endl;
return 0;
}
(is that polymorphism ?).
Not the way you have done it. It would be polymorphism if you had a pointer of type A* which pointed to what was actually a B object, and calling pm on that pointer correctly invoked the member function of B. This would only be possible if the pm function in A were declared as virtual, like below.
class A
{
...
virtual void pm(){
...
};
...
int main()
{
A* = new B();
A->pm(); //"Hello from B!"
}
is there any way I can get to the private data fileds from the base class
Not sure what you mean here - your example talks of a private field of the derived class.
Typically good class design means that derived class should not need to access the (private) fields of the base class, if this is needed you should make that field protected.
As to the compile error #ArunKumar got it exactly.
When you say Class B : A You inherit from A, but all the members are inherited as private by default, due to this, base class constructor is private, so you cannot use it.
However when you say Class B : public A it is the other end of the spectrum. All members of the base class retain their accesibility in the derived class (public remains public, etc)
The problem is that you're using private inheritance:
class B : A {
Inheritance through classes are private by default. Add public before A.
class B : public A {
As for your other problem...
I want to take the m_s variable, add it to another one and print out their sum.
This is easy when it comes to std::string. Just create another member function:
void addTom_s(string s) { m_s += s; }
Trying changing class B : A to class B : public A
From an answer on Inheritance: why is there a difference in behaviour between inherited and supplied variables?, I understand that the below code prints 0 because there is only one copy of x.
#include<iostream>
using namespace std;
class A {
public:
int x;
A() { x = 10; }
};
class B : public A {
public:
B() { x = 0; }
};
int main() {
A* ab = new B;
cout << ab->x << endl; // prints 0
}
But does this not go against the very meaning of inheritance?
I coded class B to interit publicly from class A, and I expected it to inherit a copy of member variable x, which should have resulted in ab->x printing value 10.
What am I missing here? I am finding it too difficult to understand why this prints 0 despite inheritance.
Here is a simple figure that briefly explains inheritance in terms of member variables:
When the ChildClass is created, the BaseClass is created and exists inside the ChildClass. Variables a, b and c can be accessed from both ChildClass and Baseclass (depending on access modifiers such as public, private and protected). They're shared, not copied.
I expected it to inherit a copy of member variable x
No, you don't inherit by copying. B inheriting A results in every object of B containing a subobject of type A. Since x is defined in A, you modify the A subobject by assigning to x.
The following reformulation of the code makes this subobject visible:
#include <iostream>
using namespace std;
struct A {
int x;
A() { x = 10; }
};
struct B {
A subobject;
B(): subobject() { this->subobject.x = 0; }
};
int main() {
B* ab = new B;
cout << ab->subobject.x << endl; // prints 0
}
This is of course not identical to inheritance since the types A and B are now not related any more (you cannot convert from B to A), but it is somewhat analogous to what the compiler sees when you use inheritance.
inherit a copy of member variable x - well, it doesn't inherit a copy, it just inherits the variable. and it did.
First the constructor of A runs (x=10), the the constructor of B (x=0). After that, x is obviously 0.
Based on your comment, I think your looking for composition and not inheritance:
class B {
public:
A a;
int x;
};
B inherits x from A (with the value 10 set in A's constructor), but then immediately sets it to 0 in its own constuctor.
There is only one x shared by A and B.
Or to put it another way, there is no implicit 0-ness or 10-ness to the member x. What happens, happens because you call the constructor of B with the new call. Whether the x is defined in A or in B or as a global variable, doesn't matter. The constructor of B sets it to 0, so it is 0.
Does this help?
Can you explain why this is not allowed,
#include <stdio.h>
class B {
private:
int a;
public:
int a;
};
int main() {
return 0;
}
while this is?
#include <stdio.h>
class A {
public:
int a;
};
class B : public A{
private:
int a;
};
int main() {
return 0;
}
In both the cases, we have one public and one private variable named a in class B.
edited now!
In both the cases, we have one public
and one private variable named a in
class B.
No, thats not true.
In the first case, you can't have two identifiers with the same name in the same scope. While in the second case, B::a hides A::a, and to access A::a you have to fully qualify the name:
b.a = 10; // Error. You can't access a private member.
b.A::a = 10; // OK.
Because B::a hides A::a in the second example. You can still access it, but it needs explicit qualification for the compiler to figure out you are asking for the member of parent class with the same hame.
In the first example both a's are in the same scope, while in the second example the scopes are different.
Class B in the first example is not valid because C++ cannot distinguish members by their access specifiers (public/private/protected). However, namespaces are a way for C++ to distinguish members. In class B in the second code you don't have a "public a" and a "private a", you have B::a and A::a.
Even if declaring members of the same name/signature with different access specifiers was allowed, there would be no way to address the correct member.
The first isn't allowed because it leads to ambiguous definitions. In the 2nd, although you do have both a public and a private a integer variable, you've hidden A::a inside your B class. The compiler knows implicitly what you want because there is a way to explicitly access a hidden variables.
I also believe that it boils down to name mangaling: storage specifiers don't end up as part of the actual name. I could be wrong on this however.
The easiest way to illustrate why one is allowed and why the other isn't is to look at how the compiler would compile a member function that uses each variable.
Inside your class b:
class b {
int a;
public:
int a;
void myMethod()
{
a = 10; //what a should the compiler use? Ambiguous, so the compiler sez BZZT.
}
}
For the 2nd example:
class A
{
public:
int a;
}
class B: public A
{
private:
int a;
void someMethod()
{
a = 10; //implied that you are using B::a (which may be a programmer error)
}
}