Ctype i; i.f();
where is f()
?
C = i's declared class (Ctype, in this case). while C::f() does not exist if C does not have a parent error: f() not found. C = C's parent class
f()
.
i
's declared type.
i
's static type.
class VirtualFileSystem { status open(string name, mode m) { } } class ext2 : VirtualFileSystem { status open(string name, mode m) { // whatever } }
static ext2 linux_fs VirtualFileSystem * vfs = &linux_fs vfs->open("joe", VirtualFileSystem::read)
where is open()
?
VirtualFileSystem
, which is not what we
want.
vfs
's declared (or static) type is VirtualFileSystem
.
C = i's value's declared class (ext2) while C::f() does not exist if C does not have a parent error: f() not found. C = C's parent class
Dynamic look-up correctly finds ext2::open()
.
virtual
keyword
makes the member function virtual.
class ext2 : VirtualFileSystem virtual status open(...);
virtual
when defining member functions outside the
class.
virtualVirtualFileSystem::status ext2::open(...) { ... }
virtual
is a per-function keyword.
virtual
keyword necessary.
class DeviceInterface { bool initialized(void); virtual status open(...) { } } class VirtualFileSystem : DeviceInterface { virtual status rename(...) { } } class ext2 : VirtualFileSystem { status open(...) { ... } status rename(...) { ... } } class ntfs : VirtualFileSystem { virtual status open(...) { ... } virtual bool initialized(void); }
VirtualFileSystem::open()
is virtual.
DeviceInterface::open()
is virtual.
class DeviceInterface bool initialized(void) { } class VirtualFileSystem : DeviceInterface virtual bool initialized(void) { } class HFS : VirtualFileSystem bool initialized(void) { } static HFS mac_fs VirtualFileSystem & vfs = mac_fs DeviceInterface * dip = &mac_fs
vfs.initialized()
?
dip->initialized()
?
class DeviceInterface bool initialized(void) { } class VirtualFileSystem : DeviceInterface virtual bool initialized(void) { } class HFS : VirtualFileSystem bool initialized(void) { } static HFS mac_fs VirtualFileSystem & vfs = mac_fs DeviceInterface * dip = &mac_fs
Where is vfs.initialized()
?
vfs
has static type VirtualFileSystem
.initialized()
is virtual in VirtualFileSystem
.vfs
has dynamic type HFS
.HFS::initialized()
.
Where is dip->initialized()
?
dip
has static type DeviceInterface
.initialized()
is non-virtual in DeviceInterface
.DeviceInterface::initialized()
.
class Number { ... } class Complex : Number { ... } void f() Number * np = new Complex() delete np
What happens when delete np
is called?
Number::~Number
is not virtual, static look-up is used and
Complex::~Complex
is never called.
$ cat t.cc struct Number virtual void output(ostream &); struct Complex : Number void output(ostream &) const cout << "Hello from Complex::output().\n" int main() Complex c ; c.output(cout) $ g++ -o t t.cc /tmp/f.o(.gnu.linkonce.d._vt.7Complex+0xc): undefined reference to Number::output(ostream &) /tmp/f.o: In function Complex type_info function: /tmp/f.o(.gnu.linkonce.t.__tf7Complex+0x1c): undefined reference to Number type_info function /tmp/f.o: In function Number::Number(void): /tmp/f.o(.Number::gnu.linkonce.t.(void)+0x8): undefined reference to Number virtual table collect2: ld returned 1 exit status $ CC -c t.cc "t.cc", line 15: Warning: Complex::output hides the virtual function Number::output(basic_ostream<char, char_traits<char>>&) 1 Warning(s) detected. $
$ cat t.cc struct Number virtual void output(ostream &) const { }; struct Complex : Number void output(ostream &) const cout << "Hello from Complex::output().\n"; int main() Complex c ; c.output(cout) $ g++ -o t t.cc $ CC -o t t.cc $
struct A virtual void hi(unsigned) { ... } virtual void bye(int) { ... } struct B : A void hi(int) { ... } void bye(int) { ... } int main() B b A * ap = &b ap->hi(0) // B::hi() ap->bye(0) // A::bye()
void hi(unsigned)
isn't the same as
void hi(int)
.
const
struct A virtual void hi(void) { ... } virtual void bye(void) const { ... } struct B : A { void hi(void) const { ... } void bye(void) const { ... } int main() { B b A * ap = &b ap->hi() // ?::hi() ap->bye() // ?::bye() }
const
member-function modifier takes part too.
B::bye()
A::hi()
void hi(void)
does not match
void hi(void) const
.
struct Number { virtual void output(ostream &) = 0; };
abstract
again in the child.
This page last modified on 11 December 2002.