Problems accessing methods of derived class

J

Jessica

I have a base class and a derived class, but I am getting errors when I
try to access functions of the derived class.

Simplified version of my code is as follows:

////////////////
// test2.hh

class BaseClass {

public:
BaseClass();
~BaseClass();

};

class DerivedClass : public BaseClass {

public:
DerivedClass() {}
~DerivedClass() {}

void setup();

};

////////////////
// test2.cc

#include "test2.hh"

int main() {

BaseClass* object;

object = new DerivedClass();
object->setup();

return 0;
}


When I try to compile this, I get the error:
test2.cc:8: error: `setup' undeclared (first use this function)


If I change the line to say:
object->DerivedClass::setup();

I get the error:
test2.cc:8: error: type `DerivedClass' is not a base type for type
`BaseClass'


And if I change the pointer declaration to say:
DerivedClass* object;

I get the linker error:
/tmp/ccaPvY8l.o: In function `main':
test2.cc:(.text+0x68): undefined reference to `DerivedClass::setup()'
/tmp/ccaPvY8l.o: In function `DerivedClass::DerivedClass[in-charge]()':
test2.cc:(.gnu.linkonce.t._ZN12DerivedClassC1Ev+0xd): undefined
reference to `BaseClass::BaseClass[not-in-charge]()'
collect2: ld returned 1 exit status


Can I change the declaration of DerivedClass so that I can use it as in
the code given? Or am I going about this the wrong way completely?
 
S

Shooting

Jessica said:
I have a base class and a derived class, but I am getting errors when I
try to access functions of the derived class.

Simplified version of my code is as follows:

////////////////
// test2.hh

class BaseClass {

public:
BaseClass();
~BaseClass();

};

class DerivedClass : public BaseClass {

public:
DerivedClass() {}
~DerivedClass() {}

void setup();

};

////////////////
// test2.cc

#include "test2.hh"

int main() {

BaseClass* object;

object = new DerivedClass();
object->setup();

return 0;
}


When I try to compile this, I get the error:
test2.cc:8: error: `setup' undeclared (first use this function)
You don't declare it in base class, of course you cann't use it
If I change the line to say:
object->DerivedClass::setup();

I get the error:
test2.cc:8: error: type `DerivedClass' is not a base type for type
`BaseClass'
This syntax is for you to call the function defined in base.
And if I change the pointer declaration to say:
DerivedClass* object;

I get the linker error:
/tmp/ccaPvY8l.o: In function `main':
test2.cc:(.text+0x68): undefined reference to `DerivedClass::setup()'
/tmp/ccaPvY8l.o: In function `DerivedClass::DerivedClass[in-charge]()':
test2.cc:(.gnu.linkonce.t._ZN12DerivedClassC1Ev+0xd): undefined
reference to `BaseClass::BaseClass[not-in-charge]()'
collect2: ld returned 1 exit status
This is because you only defined the function but not define it
Can I change the declaration of DerivedClass so that I can use it as in
the code given? Or am I going about this the wrong way completely?

Yeah, you have to study more carefully on c++

Just declare a setup() in Base class as a virtual function, you'll get
what you want
 
S

Salt_Peter

Jessica said:
I have a base class and a derived class, but I am getting errors when I
try to access functions of the derived class.

Simplified version of my code is as follows:
int main() {

BaseClass* object;

object = new DerivedClass();
object->setup();

return 0;
}

OK, you are going to learn something today.

If you plan to use a pointer to a base class, you are attempting to
implement a polymorphic solution. That means that you have to equip
your classes with a vtable. The way this is done is simply by declaring
at least one function as virtual. In this case, a virtual destructor
will suffice. That means that you constructing a C++ program, not C.

Also, if the plan is to reuse these various classes, declare them in
their own headers with include guards. So you'll need 2 header files, 2
corresponding implementation files (which i'm skipping here) + an
implementation file for main(). My guess is that you are looking to
make setup() virtual as well.

Note that #ifndef, #define and #endif are used to supply header guards
in order to prevent your linker from including the same header file
multiple times. For all intensive purposes, you can ignore include
guards when you are reading these classes. Include guards are only for
the linker.

////////////////
// baseclass.h

#ifndef BASECLASS_H_
#define BASECLASS_H_

class BaseClass
{

public:
BaseClass() { }
virtual ~BaseClass() { }
virtual void setup() { }
};

#endif /* BASECLASS_H_ */

////////////////
// derivedclass.h

#ifndef DERIVEDCLASS_H_
#define DERIVEDCLASS_H_

#include "baseclass.h"

class DerivedClass : public BaseClass
{
public:
DerivedClass() { }
~DerivedClass() { } // virtual
void setup() { } // virtual
};

#endif /* DERIVEDCLASS_H_ */

////////////////
// proj_test.cpp

#include "derivedclass.h"

int main()
{
BaseClass* object;
object = new DerivedClass;
object->setup();
delete object;

return 0;
}

Note that DerivedClass's destructor and DerivedClass's setup() are
virtual because of inheritance.

When I try to compile this, I get the error:
test2.cc:8: error: `setup' undeclared (first use this function)

Thats because you never provided setup's implementation.
void setup(); // is a declaration with no implementation (yet)
void setup() { } // is a declaration with implementation which doesn't
do anything right now
If I change the line to say:
object->DerivedClass::setup();

I get the error:
test2.cc:8: error: type `DerivedClass' is not a base type for type
`BaseClass'

Their isn't any vtable available and DerivedClass is not a base class.
And if I change the pointer declaration to say:
DerivedClass* object;

I get the linker error:
/tmp/ccaPvY8l.o: In function `main':
test2.cc:(.text+0x68): undefined reference to `DerivedClass::setup()'
/tmp/ccaPvY8l.o: In function `DerivedClass::DerivedClass[in-charge]()':
test2.cc:(.gnu.linkonce.t._ZN12DerivedClassC1Ev+0xd): undefined
reference to `BaseClass::BaseClass[not-in-charge]()'
collect2: ld returned 1 exit status

The compiler is basicly telling you that their is no base class
available with an implementation of setup() available to compile with.

Note that you can seperate your declaration and implementation like
so...

////////////////
// derivedclass.h

#ifndef DERIVEDCLASS_H_
#define DERIVEDCLASS_H_

#include "baseclass.h"

class DerivedClass : public BaseClass
{
public:
DerivedClass();
~DerivedClass();
void setup();
};

#endif /* DERIVEDCLASS_H_ */

////////////////
// derivedclass.cpp

#include "derivedclass.h"

DerivedClass::DerivedClass()
{
}

DerivedClass::~DerivedClass()
{
}

void DerivedClass::setup()
{
}

/* end of derivedclass.cpp */
Can I change the declaration of DerivedClass so that I can use it as in
the code given? Or am I going about this the wrong way completely?

To implement a polymorphic solution, you need to compile a C++ program
with the base class equipped with a vtable (at least one virtual
function - a virtual destructor wiil do)

Just for the sake of clarity, try compiling the following and carefully
note which function gets called and what destructors get invoked. Then
try compiling the same program without the virtual keywords (virtual is
the key). Remember: virtual is what makes the vtable.

// proj_test.cpp
//

#include <iostream>
#include <ostream>

class Base
{
public:
Base() { std::cout << "Base()\n"; }
virtual ~Base() { std::cout << "~Base()\n"; }
virtual void setup() { std::cout << "Base::setup()\n"; }
};

class Derived : public Base
{
public:
Derived() { std::cout << "Derived()\n"; }
~Derived() { std::cout << "~Derived()\n"; }
void setup() { std::cout << "Derived::setup()\n"; }
};

int main()
{
std::cout << "___ Base pointer, Derived object ___\n";
Base* object;
object = new Derived;
object->setup();
delete object;

std::cout << "\n___ Base pointer, Base object ___\n";
Base* base;
base = new Base;
base->setup();
delete base;

return 0;
}

/*

___ Base pointer, Derived object ___
Base()
Derived()
Derived::setup()
~Derived()
~Base()

___ Base pointer, Base object ___
Base()
Base::setup()
~Base()

*/
 

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,968
Messages
2,570,154
Members
46,701
Latest member
XavierQ83

Latest Threads

Top