Reputation: 17
I want to show result is 2. (Now result is 1.)
How should I do? (I want to call B::test(). But Actually code cannot access b.h, b.c in main.c)
also I want to know that error from "public: virtual int test() {return 1;}" to "protected: virtual int test() {return 1;}" in a.h
the inheritance relationship are super class A sub class B super class A sub class C
but I can access A class in main.c I want to result 2. ("a.test()" could not call "b.test()")
// a.h
#ifndef _A_
#define _A_
class A {
public:
A() {};
~A() {};
//protected:
virtual int test() {return 1;}
private:
friend class B;
};
#endif
// b.h
#ifndef _B_
#define _B_
#include "a.h"
class B : public A {
public:
B() {};
~B() {};
private:
int test() override;
friend class A;
};
#endif
// b.c
#include "b.h"
int B::test()
{
return 2;
}
// c.h
#ifndef _C_
#define _C_
#include "a.h"
class C : public A {
public:
C() {};
~C() {};
private:
int test() override;
friend class A;
};
#endif
// c.c
#include "c.h"
int C::test()
{
return 3;
}
// main.c
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = new A();
cout << a->test() << "\n";
return 0;
}
Upvotes: 1
Views: 130
Reputation: 1413
Create object of type B
, you still will be able to call test
method, because A::test
is public. This code will print 2:
int main(void)
{
A *a = new B();
// ^
cout << a->test() << "\n";
delete a; // (1)
return 0;
}
Also line (1) won't work properly unless you make A
's destructor virtual (When to use virtual destructors?):
class A {
public:
A() {};
virtual ~A() {};
// ^^^^^^^
//protected:
virtual int test() {return 1;}
private:
friend class B;
};
UPD If for some reason you can't include b.h
you can do the following:
a.h
:
#ifndef _A_
#define _A_
class A {
...
};
A* CreateB();
#endif
a.c
:
#include "a.h"
#include "b.h"
...
A* CreateB() {
return new B();
}
main.c
:
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = CreateB();
cout << a->test() << "\n";
delete a;
return 0;
}
Upvotes: 0
Reputation: 3676
Consider your code:
// main.c
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = new A();
cout << a->test() << "\n";
return 0;
}
The key decider on behaviour is =new A()
.
If you change this to =new B()
then you would get the result of '2' that you want.
However, you've had added the restriction 'code cannot access b.h'. This means that =new B()
will not compile. Where does this restriction come from? You could achieve this with an extremely complicated factory pattern, but it seems unlikely this is what you are trying to do.
Access specifiers (private
, protect
, public
) should be the same for the same method (test()
in this case) at every level in the hierarchy. This is not absolutely enforced by the compiler, but is a clear best practice. There's very little difference her between making test()
private
or protected
, but in both cases the expression:
a->test()
will fail in main, because it is outside of the class, and can only access public
members.
Also worth pointing out that your friend
declarations are entirely unnecessary in the code as shown.
Upvotes: 1