Accessing Private data types - c++

#include <iostream>
using namespace std;
class A {
private :
typedef struct {
int a;
int j;
}type;
public :
A(){};
~A(){};
void CreateInstance();
};
class B : public A
{
private :
int d;
int n;
public :
B(){};
~B(){};
void CreateInstance1();
};
void A :: CreateInstance()
{
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
void B :: CreateInstance1()
{
// I want to create a Pointer/instance of structure in this function. Dont want to use Public method in Class A
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
int main()
{
A obj;
obj.CreateInstance();
B obj1;
obj1.CreateInstance1();
cin.get();
return 0;
}
I am Looking forward to have some suggestion on this .
How can i create an instance the structure "type" in derived class.
Please let me know how i can use the "data type".
Error : 'typedef struct A :: type A :: type' is Private.
Thanks in Advance.

You cannot use anything private from the base class, it is the rule of the language.
You can, however, use anything public or protected. In you case it, probably, will be sufficient to call the base class function CreateInstance
void B :: CreateInstance1()
{
A::CreateInstance();
}
(In general it is better to keep cohesive naming: if applicable, consider declaring the function CreateInstance virtual and then rename CreateInstance1 as CreateInstance to make it an overwrite of A::CreateInstance. It is not related to the question, though).

Some possibilities:
Change type to protected (but you say you can't).
Use friend class B; in A (but then you could make the type protected too, I suppose).
Ugly hack: re-declare the struct in B, creating identical type. Then use memcpy to copy between variables of the types if needed.

#include <iostream>
using namespace std;
class A {
//woh that worked .. i did mistake here
friend class B;
private :
typedef struct {
int a;
int j;
}type;
public :
A(){};
~A(){};
void CreateInstance();
};
class B : public A
{
private :
int d;
int n;
public :
B(){};
~B(){};
void CreateInstance1();
};
void A :: CreateInstance()
{
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
void B :: CreateInstance1()
{
// I want to create a Pointer/instance of structure in this function. Dont want to use Public method in Class A
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
int main()
{
A obj;
obj.CreateInstance();
B obj1;
obj1.CreateInstance1();
cin.get();
return 0;
}

If you need it to work so badly, you can try something in these lines
Add a static method in A which creates object instances
static A::type GetTypeInstance();
A::type A :: GetTypeInstance()
{
A::type lc_Atype;
return tp;
}
So your B::CreateInstance1 will be
void B :: CreateInstance1()
{
auto A(A::GetTypeInstance());
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
Note that it creates unnecessary temporary objects if your compiler doesnt do RVO

My prev answer uses C++11. Here's another way of doing this without auto.
class A {
private :
typedef struct {
int a;
int j;
}type;
public :
A(){};
~A(){};
void CreateInstance();
typedef type AType; **//Added this typedef**
};
Change your B :: CreateInstance1 to
void B :: CreateInstance1()
{
A::AType A; **//Now this works**
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
This solution works because private hides the name and not the type as such. So we can can still expose type by wrapping it using public typedef.

Related

Two Classes Befriending Each Other

I'm trying to make two classes friend with each other, but I keep getting a "Use of Undefined type A" error message.
Here is my code:
I've tried to add class A; as shown on top but still the same.
#include <iostream>
class A;
class B
{
private:
int bVariable;
public:
B() :bVariable(9){}
void showA(A &myFriendA)
{
std::cout << "A.aVariable: " << myFriendA.aVariable << std::endl;// Since B is friend of A, it can access private members of A
}
friend class A;
};
class A
{
private:
int aVariable;
public:
A() :aVariable(7){}
void showB(B &myFriendB){
std::cout << "B.bVariable: " << myFriendB.bVariable << std::endl;
}
friend class B; // Friend Class
};
int main() {
A a;
B b;
b.showA(a);
a.showB(b);
system("pause");
return 0;
}
I'm trying to make class A access class B and vice versa via the friendship.
You can't access myFriendA.aVariable because the compiler doesn't know it exists. All it knows is that a class A exists (because of the forward declaration on the second line), but it hasn't been fully defined so it has no idea what its members/methods are.
If you wanted to make this work, showA() would have to be declared outside of the class scope.
class A;
class B
{
private:
int bVariable;
public:
B() :bVariable(9){}
void showA(A &myFriendA);
friend class A;
};
class A
{
private:
int aVariable;
public:
A() :aVariable(7){}
void showB(B &myFriendB){
std::cout << "B.bVariable: " << myFriendB.bVariable << std::endl;
}
friend class B; // Friend Class
};
// Define showA() here
void B::showA(A &myFriendA)
{
std::cout << "A.aVariable: " << myFriendA.aVariable << std::endl;
}
int main() {
A a;
B b;
b.showA(a);
a.showB(b);
system("pause");
return 0;
}
As #user888379 pointed out, moving the implementation of showA and showB methods after both classes have been completely declared will solve your problem. Following is working code:
#include <iostream>
class A;
class B
{
private:
int bVariable;
public:
B() :bVariable(9){}
void showA(A &myFriendA);
friend class A; // Friend Class
};
class A
{
private:
int aVariable;
public:
A() :aVariable(7){}
void showB(B &myFriendB);
friend class B; // Friend Class
};
void B::showA(A &myFriendA) {
std::cout << "A.aVariable: " << myFriendA.aVariable << std::endl; // Since B is friend of A, it can access private members of A
}
void A::showB(B &myFriendB) {
std::cout << "B.bVariable: " << myFriendB.bVariable << std::endl; // Since A is friend of B, it can access private members of B
}
int main() {
A a;
B b;
b.showA(a);
a.showB(b);
return 0;
}
Read this answer for more detailed analysis.

Is it possible to replace a parent class?

If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.

C++ overloading method based on derived class

I am facing the following problem with my code:
#include <iostream>
using namespace std;
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
int main()
{
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(b);
return 0;
}
And here the compiler complains about the sayHello(b); line in the
code.
"call of overloaded 'sayHello(Base*&)' is ambiguous"
Is there a way to solve this problem?
EDIT:
I basically want to pass my object to a function that does some calculations based on the type of the object. My object intentionally lacks of information in order to make the needed calculations. So Impl1 and Impl2 just contain some basic data, without the knowledge of more data needed to do the calculations.
Overload resolution is performed at compile time. It means for sayHello(b);, the compiler only know that the type of b is Base*, it won't and can't know that b is pointing to a Impl1 object actually. Then results in ambiguous call; converting Base* to Impl1* or Impl2* is equivalent rank for the call.
PS: might be OT, but for you code sample, a function taking a Base* would work fine; dynamic dispach will take effect.
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Base *i) {
cout << "Some derived class of Base says: ";
i->sayHello();
}
int main()
{
Impl1 i1;
Impl2 i2;
Base *b = &i1;
sayHello(b); // "Hi from Impl1"
b = &i2;
sayHello(b); // "Hi from Impl2"
return 0;
}
If you need to know the dynamic type at run-time, you can use dynamic_cast. e.g.
Base *b = /* something */;
Impl1 * pi1 = dynamic_cast<Impl1*>(b);
if (pi1 != nullptr) sayHello(pi1);
Since overloads are resolved at compile time, you have to supply the compiler with the exact type in order for the overload resolution to succeed.
In order to dispatch on the type, add a virtual member function to the Base, and use it to choose the overload:
class Base {
public:
virtual void sayHello()=0;
virtual void callSayHello() = 0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
void callSayHello() {sayHello(this); }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
void callSayHello() {sayHello(this); }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
...
b->callSayHello();
Note that implementations of callSayHello are identical, but you cannot place them into Base class, because the type of this would be different.
Note: the idea for this implementation is borrowed from C++ implementation of the Visitor Pattern.
Get rid of the two free-standing functions and call b->sayHello(); directly:
Impl1 *i1 = new Impl1();
Base *b = i1;
b->sayHello();
Or use an ugly workaround with dynamic_cast:
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(dynamic_cast<Impl1*>(b));
The need to resort to dynamic_cast often suggests an error in the class design. This may very well be the case here. Chances are that you should never have introduced a supposedly object-oriented base class in the first place.
Note also that you do not call delete at the end. If you do, you will need a virtual destructor in Base.

Injecting a function into a subclass

Is it possible to do such things in C++14. I have a base class as follows:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
class ConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //1
}
};
class SuperConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //2
}
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
As you can see at //1 and //2, the function's body is completely similar. But I can't quite move it into a base class because of depending on the static type of this. In spite of that fact, I wouldn't like to write absolutely the same code every time I need to add one more subclass of AbstractElement. So, I need some kind of mechanism which provides us with the facility to inject code into a function.
As long as marcos are not very desirable solution, I'd like to ask about some tricks that can be done in C++14 for solving such a problem.
Yes, it is possible using CRTP:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
template <class T>
class CRTPAbstractElement : public AbstractElement
{
B _b;
public:
virtual void foo()
{
T* t = dynamic_cast<T *>(this);
_b.bar(t);
}
};
class ConcreteElement : public CRTPAbstractElement<ConcreteElement>
{
};
class SuperConcreteElement : public CRTPAbstractElement<SuperConcreteElement>
{
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
By adding an intermediate CRTP class we are able to cast a pointer to the base class to a pointer to the derived class. Thus solving the issue of code duplication.

Implicit Conversion

My program was:-
#include < iostream.h>
#include < conio.h>
struct base
{
protected:
void get()
{
cin>>a>>b;
}
public:
base(int i=0, int j=0);
void put()
{
cout << a << '\t' << b << "\tput 1";
}
int a,b,c;
~base()
{
cout << "base destroyed";
}
};
class deri : protected base
{
int c,d;
char w;
int ans;
public:
deri(int r=7, int s=0)
: base(r,s)
{
c=r;
d=s;
cout << "\nDerived invoked\n";
}
void put()
{
cout << c << '\t' << d << '\t' << a << '\t' << b;
}
};
class d2 : protected deri
{
public:
d2() {}
void start();
void add()
{
get(); // ERROR HERE: Implicit conversion of 'd2 *' to 'base *' not allowed
}
~d2(){}
};
void d2::start()
{
put();
}
base::base(int i, int j)
{
a=i;
b=j;
cout << "\nbase invoked\n";
cout << "Enter a,b: ";
get();
}
void main()
{
clrscr();
getch();
}
CAN anyone explain what the error msg means?
You are probably using an old compiler as you're including <iostream.h> instead of the new standard <iostream> and you aren't using namespace std.
After fixing this, adding the line using namespace std; on top and commenting out clrscr() your code compiles fine on MSVC8.
Do you have a clear reason to use protected derviation ? If not, I'd suggest using public derviation instead. protected derviation is something really quite complicated and uncommon.
When you derive a base class using protected or private then your derived class is not treated as base class and compiler will not perform implicit type conversion in that case.
Derived class in not base class in case of private or protected inheritance.
whereas in case of public inheritance every derived class is a base class .
Try out explicit type casting in the function or make inheritance public.