Partial implementation in derived classes

A

Alex Vinokur

I tried to build program with partial implementation.
However a linker generates errors.

Is there any approach that enables to use partial implementation for similar purposes?

------ foo.cpp ---
struct Base
{
virtual void foo1() = 0;
virtual void foo2() = 0;
};

struct Derived1 : public Base
{
void foo1() {}
void foo2(); // Not for use
};

struct Derived2 : public Base
{
void foo1(); // Not for use
void foo2() {}
};

int main ()
{
Base* p1 = new Derived1();
Base* p2 = new Derived2();
// -----------------------
// I would like to get linkage error in the following cases:
// p1->foo2();
// p2->foo1();
// -----------------------
return 0;
}
------ foo.cpp ---


------ Compilation ------
// gpp: GNU C++ 4.0.1 (DJGPP)

$ gpp foo.cpp

c:/djgpp/tmp/cccl1W22.o:foo.cpp:(.gnu.linkonce.t._ZN8Derived1C1Ev+0x16): undefined reference to `vtable for Derived1'
c:/djgpp/tmp/cccl1W22.o:foo.cpp:(.gnu.linkonce.t._ZN8Derived2C1Ev+0x16): undefined reference to `vtable for Derived2'
collect2: ld returned 1 exit status

-------------------------


Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn
 
V

Victor Bazarov

Alex said:
I tried to build program with partial implementation.
However a linker generates errors.

Is there any approach that enables to use partial implementation for
similar purposes?

------ foo.cpp ---
struct Base
{
virtual void foo1() = 0;
virtual void foo2() = 0;
};

struct Derived1 : public Base
{
void foo1() {}
void foo2(); // Not for use
};

struct Derived2 : public Base
{
void foo1(); // Not for use
void foo2() {}
};

int main ()
{
Base* p1 = new Derived1();
Base* p2 = new Derived2();
// -----------------------
// I would like to get linkage error in the following cases:
// p1->foo2();
// p2->foo1();
// -----------------------
return 0;
}
------ foo.cpp ---


------ Compilation ------
// gpp: GNU C++ 4.0.1 (DJGPP)

$ gpp foo.cpp

c:/djgpp/tmp/cccl1W22.o:foo.cpp:(.gnu.linkonce.t._ZN8Derived1C1Ev+0x16):
undefined reference to `vtable for Derived1'
c:/djgpp/tmp/cccl1W22.o:foo.cpp:(.gnu.linkonce.t._ZN8Derived2C1Ev+0x16):
undefined reference to `vtable for Derived2' collect2: ld returned 1
exit status

You're in violation of the Standard requirement: a virtual function shall
be either defined or declared pure (or both). You cannot have a virtual
function declared [normal] and not defined.

You could try accomplishing "partial implementation" if the functions you
don't want to define (and call) are _non-virtual_.

V
 
J

Jonathan Mcdougall

Alex said:
I tried to build program with partial implementation.
However a linker generates errors.

Is there any approach that enables to use partial implementation for similar purposes?

------ foo.cpp ---
struct Base
{
virtual void foo1() = 0;
virtual void foo2() = 0;
};

struct Derived1 : public Base
{
void foo1() {}
void foo2(); // Not for use
};

struct Derived2 : public Base
{
void foo1(); // Not for use
void foo2() {}
};

This is illegal. Non-pure virtual functions must be defined, even if
not used. See 10.4§4.
int main ()
{
Base* p1 = new Derived1();
Base* p2 = new Derived2();
// -----------------------
// I would like to get linkage error in the following cases:
// p1->foo2();
// p2->foo1();
// -----------------------
return 0;
}

That's impossible. In order to instantiate a class, it must be
concrete. For a class to be concrete, all its pure virtual functions
(inherited or not) must have a *definition*.

If Base does something a Derived cannot, then Derived is not a Base.
Review your design (see
http://www.parashift.com/c++-faq-lite/proper-inheritance.html for more
informations).


Jonathan
 
R

Rolf Magnus

Alex said:
I tried to build program with partial implementation.
However a linker generates errors.

Is there any approach that enables to use partial implementation for
similar purposes?

------ foo.cpp ---
struct Base
{
virtual void foo1() = 0;
virtual void foo2() = 0;
};

struct Derived1 : public Base
{
void foo1() {}
void foo2(); // Not for use
};

What do you mean "not for use"? Why do you derive from a class that has a
virtual member function with that name if you don't want it to be used? If
a function that gets a pointer to the base class calls foo2() without
knowing that it's actually a Derived1 (which is what virtual member
functions are for), what would you expect to happen?
struct Derived2 : public Base
{
void foo1(); // Not for use
void foo2() {}
};

int main ()
{
Base* p1 = new Derived1();
Base* p2 = new Derived2();
// -----------------------
// I would like to get linkage error in the following cases:
// p1->foo2();
// p2->foo1();

How would that work? Virtual functions are resolved at run-time. You can't
get a compile-time error for an error that occurs at run-time. Consider:

Base* p;
int x;
std::cout << "Derived1 (1) or Derived2 (2)? "
std::cin >> x;
if (x == 1)
p = Derived1();
else if (x == 2)
p = Derived2();

std::cout << "foo1 (1) or foo2 (2)? "
std::cin >> x;
if (x == 1)
p->foo1();
else if (x == 2)
p->foo2();

Now how would the compiler know at compile-time what the user will choose?

But you could e.g. throw an exception in the derived class's implementation.
 
A

Alex Vinokur

Rolf Magnus said:
Virtual functions are resolved at run-time. You can't
get a compile-time error for an error that occurs at run-time.
[snip]

It seems that for the same reason a private method can be invocated as interface in a derived class.

------ foobar.cpp ------
#include <iostream>
using namespace std;

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

class Derived : public Base
{
private:
void foo() { cout << "foo(): I am private" << endl; }
};

int main ()
{
Base* p = new Derived();

p->foo();

return 0;
}

------ foobar.cpp ------

------ Run ------

$ ./a.exe

foo(): I am private
 
P

Phlip

Alex said:
It seems that for the same reason a private method can be invocated as
interface
in a derived class.

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

class Derived : public Base
{
private:
void foo() { cout << "foo(): I am private" << endl; }
};

int main ()
{
Base* p = new Derived();
p->foo();
return 0;
}

Right. Access is checked at compile time, and virtual methods

Now why does /C++ Coding Standards/, by Alexandrescu & Herb Sutter,
recommend (IIRC) "Prefer to make virtual functions private"? Does that imply
both the Base and Derived methods should be private?
 
P

Phlip

Right. Access is checked at compile time, and virtual methods

....dispatch at runtime.
 
A

Alf P. Steinbach

* Phlip:
Right. Access is checked at compile time, and virtual methods

Now why does /C++ Coding Standards/, by Alexandrescu & Herb Sutter,
recommend (IIRC) "Prefer to make virtual functions private"? Does that imply
both the Base and Derived methods should be private?

I can't speak for the authors, but one possible reason is that it forces
derived classes -- and client code -- to call virtual functions via
non-virtual ones that can e.g. detect contract violations and serve as
scaffolding for overrides in derived classes. E.g., you might want to
log all calls to some function, and centralize that in the base class.
But if virtual functions are called directly you can't, because the
calls might go directly to an override in a derived class (this is the
"any CS problem can be solved by an additional layer of indirection").

IMO that's not much of an advantage, though.

With private virtual functions one runs the risk of a derived class
overriding some undocumented private virtual function in a base class,
or else, the private virtuals must be documented, which is somewhat at
odds with the notion of using private for implementation details (but
then, also a private base class can affect derived class code).

Perhaps the most that nearly everyone can agree with is that the C++
concepts of public, protected and private do not correspond to the
notions of data hiding & encapsulation that we commonly apply at design
level thinking -- where "private" is really private, hidden detail.

And with such conceptual mismatch, what's reasonable and unreasonable
use becomes very subjective, a matter of resolving the conflict in a
subjectively least painful way.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,585
Members
45,082
Latest member
KetonaraKetoACV

Latest Threads

Top