简体   繁体   中英

C++ inheritance & virtual function problem

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 bh, 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 ah

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;
}

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.

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 bh you can do the following:

ah :

#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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM