Reputation: 4963
I am teaching myself to write classes in C++ but can't seem to get the compilation to go through. If you can help me figure out not just how, but why, it would be greatly appreciated. Thank you in advance! Here are my three files:
make_pmt.C
#include <iostream>
#include "pmt.h"
using namespace std;
int main() {
CPMT *pmt = new CPMT;
pmt->SetVoltage(900);
pmt->SetGain(2e6);
double voltage = pmt->GetVoltage();
double gain= pmt->GetGain();
cout << "The voltage is " << voltage
<< " and the gain is " << gain << "." <<endl;
return 0;
}
pmt.C
#include "pmt.h"
using namespace std;
class CPMT {
double gain, voltage;
public:
double GetGain() {return gain;}
double GetVoltage() {return voltage;}
void SetGain(double g) {gain=g;}
void SetVoltage(double v) {voltage=v;}
};
pmt.h
#ifndef PMT_H
#define PMT_H 1
using namespace std;
class CPMT {
double gain, voltage;
public:
double GetGain();
double GetVoltage();
void SetGain(double g);
void SetVoltage(double v);
};
#endif
And for reference, I get a linker error (right?):
Undefined symbols:
"CPMT::GetVoltage()", referenced from:
_main in ccoYuMbH.o
"CPMT::GetGain()", referenced from:
_main in ccoYuMbH.o
"CPMT::SetVoltage(double)", referenced from:
_main in ccoYuMbH.o
"CPMT::SetGain(double)", referenced from:
_main in ccoYuMbH.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Upvotes: 1
Views: 478
Reputation: 224129
First some taxonomy.
This
class CPMT {
public:
double GetGain();
// ...
};
is defining a class without also defining the member functions. This
class CPMT {
public:
double GetGain() {return gain;}
// ...
};
is defining the same class, with also defining its member functions (implicitly) inline. This
double CPMT::GetGain() {return gain;}
// ...
is defining the member functions (not inline).
Now, if you want to separate implementation from interface, your header needs to define the class, while your implementation file needs to define its member functions. So the pure class definition
class CPMT {
public:
double GetGain();
//...
};
goes into the header file and the implementation
double CPMT::GetGain() {return gain;}
// ...
goes into the implementation file - except for those member functions you want to implement inline. Since inline
asks the compiler to substitute a function's implementation for every call to it, the implementation must be present where the function is called. That's why the implementations of inlined functions must be in header files.
There are two ways to inline a member function. One is to define it within its class's definition
class CPMT {
public:
double GetGain() {return gain;}
// ...
};
which implicitly makes it inline
. The other is to explicitly inline it
class CPMT {
public:
double GetGain();
//...
};
inline double CPMT::GetGain() {return gain;}
// ...
In both cases the implementation must be in the header file.
Upvotes: 6
Reputation: 15126
In pmt.c, you're redefining the class. Instead, you should just define its functions:
double CPMT::GetGain() { return gain; }
double CPMT::GetVoltage() {return voltage;}
void CPMT::SetGain(double g) {gain=g;}
void CPMT::SetVoltage(double v) {voltage=v;}
Also, you need to make sure that you're providing both object files to the linker.
Upvotes: 4
Reputation: 6705
pmt.C would look like this:
#include "pmt.h"
using namespace std;
double CPMT::GetGain() {return gain;}
double CPMT::GetVoltage() {return voltage;}
void CPMT::SetGain(double g) {gain=g;}
void CPMT::SetVoltage(double v) {voltage=v;}
I compiled it like this:
g++ make_pmt.C pmt.C
You also need to add a constructor and initialize gain and voltage.
Upvotes: 6
Reputation: 455292
Looks like you are compiling and linking individual .C files which are not complete by themselves. You need to compile them first to get .o
file and then link the .o
files to get the final executable. This all can be done using:
g++ make_pmt.C pmt.C
Also the pmt.C should have only definition of the functions declared in the header file.
Upvotes: 1
Reputation: 8643
Try renaming the files .cpp or .cxx, your compiler may be assuming that .C means it is C and not C++, which seems to be the case since it isn't mangling the names.
Upvotes: 1
Reputation: 3122
The syntax of your pmt.C file is wrong. It should read
double CPMT::GetGain() {return gain;}
double CPMT::GetVoltage() {return voltage;}
void CPMT::SetGain(double g) {gain=g;}
void CPMT::SetVoltage(double v) {voltage=v;}
Upvotes: 4