0

I know why I want to use private virtual functions, but how exactly can I implement them?

For example:

class Base{
[...]
private:
 virtual void func() = 0;
[...]
};

class Derived1: public Base{
  void func() 
  { //short implementation is ok here
  }
};

class Derived2: public Base{
  void func(); //long implementation elsewhere (in cpp file)
};

[...] 

void Derived2::func()
{ //long implementation 
}

The first version is ok but not always possible. Isn't the second version simply name hiding? How do you define the Base::func() of Derived2, if you cannot do it within the class declaration of Dereived2?

Thanks

Community
  • 1
  • 1
Dane
  • 133
  • 1
  • 11
  • 1
    Why does it have to be private? protected would make more sense. Could you elaborate, please? –  Mar 16 '10 at 15:00
  • 4
    `Derived2::func()` is a correct override for `Base::func()`, what exactly isn't working for you? – CB Bailey Mar 16 '10 at 15:01
  • 1
    Can you elaborate on "but not always possible"? – philsquared Mar 16 '10 at 15:02
  • @dbemerlin: Sometimes it's also called the "Non-virtual inheritance" idiom or "Template Method" pattern. Just follow the link in the question. – sbi Mar 16 '10 at 15:05
  • @dbemerlin: you'd make it private if it's only meant to be called from the base class, but implemented by derived classes. The Template Method pattern is an example of this. – Mike Seymour Mar 16 '10 at 15:06
  • @gf : doh! ;-D @dbemerlin : please check the link in the 'why' @Phil Nash: for example if my code conventions prohibit me to write long implementations within the class declaration (Derived1 would be ok, but not Derived2) @Charles Bailey: wouldn't be the empty declaration of the `func()` in `Derived2` be a declaration of `Derived2::func()` instead of `Base::func()` ? Ohh - I just got it - it's the same in `Derived1`, private virtual function do work through name hiding, yes? – Dane Mar 16 '10 at 15:08
  • @Dane there is no name hiding going on here. You're implementing a virtual function using the correct signature - your example for Derived2 looks correct (typos aside). – philsquared Mar 16 '10 at 15:10
  • 1
    @Dane: its sufficient to provide a declaration for the override in the derived class' declaration, it doesn't matter wether you define it inline or not. In that regard, `Derived1` and `Derived2` are equivalent. – Georg Fritzsche Mar 16 '10 at 15:11
  • thanks everybody - if it isn't name hiding it should be ok! – Dane Mar 16 '10 at 15:21

3 Answers3

4

How do you define the Base::func() of Derived2, if you cannot do it within the class declaration of Dereived2?

You don't define "Base::func() of Derived2" (whatever this might be), you define Derived2::func(). This compiles just fine for me:

#include <iostream>

class Base{
private:
 virtual void foo() = 0;
public:
  void bar() {foo();}
};

class Derived: public Base{
  void foo();
};

void Derived::foo()
{
   std::cout << "inside of 'Derived1::foo()'\n";
}

int main()
{
  Derived d;
  Base& b = d;
  b.bar();
  return 0;
}

What's your problem with it?

sbi
  • 219,715
  • 46
  • 258
  • 445
  • my problem was that i thought `Derived::foo()` would declare and define a new function of Derived (not define the `Base::foo()`). But if you define your bar() function in a more ugly way: `void bar() { ((Base*)this)->foo();}` you can see that I was mistaken - it does work and hence `Base::foo()` was defined... Thanks again everybody! ` – Dane Mar 16 '10 at 15:24
3

Polymorphism and accessibility are two separate concepts. You can always override a base class' private virtual function, but you won't be able to call the base class version from anywhere but the base class itself. Also, C++ FAQ Lite has a pretty lengthy entry on the subject.

Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125
  • and my question is: how exactly? – Dane Mar 16 '10 at 14:59
  • @Kristo: You can call a private base class function if you refer to it via a derived class that changed its access mode (via `public: using Base::f;` and using `myBase->f()`). – Georg Fritzsche Mar 16 '10 at 15:03
  • 2
    @Kristo, why would you want to call the base class version if it's pure virtual anyway - the context appears to be implementing the template method, so the intention is that it will only be called by the base class itself? – philsquared Mar 16 '10 at 15:04
-2

For what I understand here, you're trying to do polymorphism.

There are 4 rules that you must follow to achieve polymorphism.

  1. You must inherit from the base class.
  2. Your functions must have the same name in every class.
  3. You need the virtual keyword in front of every function, and the override keyword at the end of the child's fonctions.
  4. You have to use a pointer on the main class, and use the "new" keyword to define it as a child type.

See this awesome wiki page for code example.

Hope this is what you wanted. ^^

Yours truly,

SeargX

Community
  • 1
  • 1
SeargX
  • 117
  • 1
  • 2
  • 10
  • 1
    #3 and #4 don't even apply to C++. – sbi Mar 16 '10 at 15:13
  • Um... yes, they do. Maybe you're not forced to use the ovveride keyword, it depends on what you want to do, but it definitly applies to C++. – SeargX Mar 16 '10 at 15:17
  • 1
    override is supported in C++ as an MS extension only (presumably because they had to implement it for C++/ CLI anyway). It is not part of standard C++ – philsquared Mar 16 '10 at 15:25
  • @SeargX: `struct Base { virtual f() {} }; struct Derived : Base { f() {} }; int main() { Derived d; Base& b; b.f(); }` doesn't need `virtual` in front of every function, doesn't use `override` at all, and it's working without pointers or `new` - yet it's employing polymorphism in C++. – sbi Mar 16 '10 at 15:34
  • I guess that I'll have some questions to ask my teachers about that... they didn't teach it that way, they did it as I posted and made it clear that it was required. I'm sorry if I was wrong, but that's what I've been taught. <. – SeargX Mar 16 '10 at 15:44
  • sbi: Yes, they did. But we always worked on either Visual Studio or Borland C++, so I guess it's not "standard" C++. – SeargX Mar 16 '10 at 17:02