0

How to avoid The private function calling indirectly using base class virtual function.

class baseclass{
public:
    virtual void printmynumber() = 0;
};

class derivedclass : public baseclass
{
private:
    int m_mynumber;
    void printmynumber()
    {
        cout << m_mynumber << endl; 
    }
public:
    derivedclass(int n)
    {
       m_mynumber = n;
    }
};


void main()
{
    baseclass *bObj = new derivedclass(10);
    bObj->printmynumber();
    delete bObj;
}

How to avoid the calling of private function?

YSC
  • 38,212
  • 9
  • 96
  • 149
Nagappa
  • 194
  • 2
  • 13

3 Answers3

3

You cannot.

void printmynumber() is part of the public API of baseclass, hence of derivedclass. If you wished derivedclass::printmynumber() not to be public, maybe derivedclass shouldn't inherit from baseclass.

As suggested in the comments, this is a violation of the Liskov substitution principle: the L in SOLID.

YSC
  • 38,212
  • 9
  • 96
  • 149
3

You can't do that with inheritance. Given a pointer to baseclass, the compiler only knows it has a public virtual function, so allows calling the function accordingly.

The derived class has elected to inherit from the base class, and has implemented a function with different access. But none of that is visible, given only a pointer to the base.

There is nothing preventing derivedclass::printmynumber() from being implemented to do nothing - which means if code calls it, there will be no observable effect (assuming absence of an expected effect is tolerable).

The real solution is to fix your design, not to try to work around deficiencies in it. Don't inherit derivedclass from baseclass. That way, no member function of derivedclass can be called at all, given only a pointer to baseclass, since the types are not related (passing a derivedclass * to a function expecting a baseclass * will normally be diagnosed as an error).

BTW: main() returns int, not void. Some compilers support void main() as a non-standard extension (and the documentation for some of those compilers falsely describes such a thing as standard) but it is better avoided.

Peter
  • 35,646
  • 4
  • 32
  • 74
  • Using an eclipse with gcc 4.8 as it allows void main() – Nagappa Jan 25 '19 at 22:50
  • 3
    @Nagappa Just because a specific compiler allows it doesn't mean it's correct. [The `main` function](https://en.cppreference.com/w/cpp/language/main_function) is required to return an `int` by the C++ specification. – Some programmer dude Jan 25 '19 at 22:52
  • @Nagappa if you dig into Eclipse's project properties (Project->Properties->C/C++ Build->Settings-> GCC C++ Compiler->Warnings) you'll find a dialog box that configures the compiler to emit more diagnostic information. Turn on *Pedantic* to see warning when you use extensions that are not part of Standard C++. While you are there, consider also turning on *All Warnings* and *Extra Warnings*. Compiler warnings are the first line of defense against logic errors, so the more work the compiler does for you, the less debugging you'll probably have to do later. – user4581301 Jan 25 '19 at 23:25
  • The difference between `int main()` and `void main()` is that the standard requires the first (otherwise an implementation cannot claim to comply with the standard) and does not require (or disallow) supporting the second. Practically, therefore, all real-world compilers support `int main()`, but not all support `void main()`. – Peter Jan 25 '19 at 23:43
2

The only way I can see to prevent it without modifying the base class, is to add another inheritance-layer between between the original base-class and the final derived class. In that middle class you make the function private or deleted. And then you use a pointer to that middle class as the base pointer.

Something like

class baseclass
{
public:
    virtual void printmynumber() = 0;
};

struct middleclass : public baseclass
{
    void printmynumber() = delete;
};

class derivedclass : public middleclass
{
private:
    int m_mynumber;
    void printmynumber()
    {
        cout << m_mynumber << endl; 
    }
public:
    derivedclass(int n)
    {
       m_mynumber = n;
    }
};


void main()
{
    // Here use the middleclass instead of the baseclass
    middleclass *bObj = new derivedclass(10);

    // printmynumber is deleted in the middleclass and can't be called
    // This will result in a build error
    bObj->printmynumber();

    delete bObj;
}

This of course requires modifications of all places where the original base class is used, but it won't need modifications to the base class itself. So it's a trade-off.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Using GCC 4.8 in eclipse and i wont this it will support c++ 11 concept to delete the funtion. Please correct me if i am wrong – Nagappa Jan 25 '19 at 22:54
  • @Nagappa I don't know about deleted functions, but GCC 4.8 do have some C++11 functionality. Try building with `-std=c++11` (or `-std=c++0x`). – Some programmer dude Jan 25 '19 at 22:55
  • @Nagappa The Language dialect options can be found at Project->Properties->C/C++ Build->Settings-> GCC C++ Compiler->Dialect in recent versions (going back a few years) of Eclipse. – user4581301 Jan 25 '19 at 23:28