There is some linking error here. I looked for that online, yet still I couldn't find the problem. How can I fix it?
g++ test.cpp -o test
/tmp/ccDfCj4N.o: In function `Interval::Interval()':
test.cpp:(.text._ZN8IntervalC2Ev[Interval::Interval()]+0x9): undefined reference to `vtable for Interval'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD0Ev[IntInterval::~IntInterval()]+0x1d): undefined reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD1Ev[IntInterval::~IntInterval()]+0x1d): undefined reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o:(.rodata._ZTI11IntInterval[typeinfo for IntInterval]+0x10): undefined reference to `typeinfo for Interval'
collect2: ld returned 1 exit status
Here is the code!
All classes are in a same file for a pilot program.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
#define MAX_IP_RANGE 4294967295
class Interval {
public:
virtual Interval * interval_copy() = 0;
virtual unsigned long get_begin() = 0;
virtual unsigned long get_end() = 0;
virtual unsigned long get_length() = 0;
virtual Interval* get_intersect(Interval *interval) = 0; // Examine whether two intervals have intersection
virtual Interval* copy() = 0;
virtual ~Interval();
virtual bool is_equal(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 == b2 && e1 == e2)
return true;
return false;
}
virtual bool is_within(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 >= b2 && e1 <= e2)
return true;
return false;
}
virtual bool contains(Interval *interval) { // Examine whether this interval contains another interval
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 <= b2 && e1 >= e2)
return true;
return false;
}
virtual bool is_empty() {
return (get_end()<get_begin())?true:false;
}
virtual bool is_intersect(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1>e2)
return false;
if (b2>e1)
return false;
return true;
}
virtual void print()
{
cout << '('<<get_begin() << ',' << get_end() << ")\n";
}
};
class IntInterval : public Interval {
private:
unsigned long begin;
unsigned long end;
IntInterval();
public:
virtual Interval * interval_copy() {
return new IntInterval(begin, end);
}
IntInterval(unsigned long a, unsigned long b): begin (a), end (b)
{}
void set_value(unsigned long a, unsigned long b) {
begin = a;
end = b;
}
void set_begin(unsigned long a) {
begin = a;
}
void set_end(unsigned long b) {
end = b;
}
virtual Interval* copy()
{
Interval *new_interval = new IntInterval(begin, end);
return new_interval;
}
virtual unsigned long get_begin() {
return begin;
}
virtual unsigned long get_length() {
return end-begin+1;
}
virtual unsigned long get_end() {
return end;
}
virtual Interval* get_intersect(Interval *interval); // Get the intersect part of two intervals
virtual ~IntInterval() {};
};
Interval* IntInterval::get_intersect(Interval *interval) {
unsigned long begin2 = interval->get_begin();
unsigned long end2 = interval->get_end();
if (end < begin2 || begin > end2) {
return new IntInterval(1, 0);
}
return new IntInterval((begin>begin2)?begin:begin2, (end<end2)?end:end2);
}
IntInterval * parse_ip(const char * _str) {
unsigned long _begin=0;
unsigned long _end=0;
string input(_str);
if (input.find('-') != string::npos){
string begin = input.substr(0, input.find('-'));
string end = input.substr(input.find('-')+1);
unsigned int ip1 = 0, ip2 = 0;
unsigned int ip3 = 0, ip4 = 0;
sscanf(begin.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
_begin = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
ip1 = 0; ip2 = 0; ip3 = 0; ip4 = 0;
sscanf(end.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
_end = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
if ((_begin > _end) || (_end > MAX_IP_RANGE)){
cout<<"ERROR: The IP INTERVAL IS WRONG The range is "<<begin<<"-"<<end<<endl;
exit(0);
}
}
return new IntInterval(_begin, _end);
}
bool compFunc (Interval * i, Interval * j) {
return (i->get_begin() < j->get_begin());
}
int main () {
vector <vector<pair<string, string> > > nets;
vector<pair<string, string> > x;
vector<pair<string, string> > y;
x.push_back(make_pair("1.1.1.1", "3.0.0.0"));
x.push_back(make_pair("10.2.5.3", "30.2.5.0"));
x.push_back(make_pair("100.2.25.2", "130.2.25.2"));
y.push_back(make_pair("41.0.2.2", "43.2.2.5"));
y.push_back(make_pair("131.2.2.2", "135.5.5.2"));
nets.push_back(x);
nets.push_back(y);
vector <IntInterval *> _nets;
for (int i=0; i<(int)nets.size(); i++)
for(int j=0; j<(int)nets[i].size(); j++) {
string s = nets[i][j].first + '-' + nets[i][j].second;
_nets.push_back(parse_ip(s.c_str()));
}
sort(_nets.begin(), _nets.end(), compFunc);
if (_nets.size()>1)
for (vector<IntInterval *>::iterator it = _nets.begin()+1; it < _nets.end(); ) {
if ((*it)->get_begin()-1 == (*(it-1))->get_end()) {
(*(it-1))->set_end((*it)->get_end());
_nets.erase(it);
}
else if ((*it)->get_begin()-1 < (*(it-1))->get_end()) {
it++;
cout<<"ERROR: Network address overlapping!"<<endl;
}
else
it++;
}
for (int i=0; i<(int)_nets.size(); i++)
cout << _nets[i]->get_begin() << " " << _nets[i]->get_end() << endl;
return 0;
}
You never provided an implementation for virtual ~Interval(); and several other functions. You must provide an implementation for all non-pure virtual functions you declare. In particular, G++ emits the vtable along with the implementation of the first-declared non-inline function in a class. Omitting its implementation means you won't have a vtable, and thus won't be able to construct the class (hence these errors).
In short, define every function you declare, except for pure virtuals. There are some cases where it's justified to leave out the definition for a declared function, but they are very rare.
I had the same problem. I was merging my code with upstream changes and picked my change over another engineer's seemingly identical change in the header file. It just turned out that they had changed the constness of the method and I hadn't noticed, and you will get this error for the reason #bdonian says.
virtual void foo(Many params, As part, Of veryLong, Method signature);
and theirs:
virtual void foo(Many params, As part, Of veryLong, Method signature) const;
When merging I picked the first version, but the implementation had the second one, resulting in the compiler assuming there is an overload of foo() that is undefined, and hence the error.
In virtual classes never put undefined functions first. Move
IntInterval();
to after the first defined function:
private:
unsigned long begin;
unsigned long end;
public:
virtual Interval * interval_copy(){return new IntInterval(begin,end);}
IntInterval(unsigned long a,unsigned long b): begin (a),
end (b)
{}
private:
IntInterval();
public:
It's because C++ glues the vtable to the first function. If you don't define it, the vtable will be undefined as well.
As mentioned by other answers, you need to also define the destructor:
public:
virtual ~IntInterval()
{
// Destruction code
}
Related
Okay so am trying to make a data structure that maintains a heap of data in order to solve within the compile-time limit. https://open.kattis.com/problems/annoyedcoworkers
I might be in over my head since I just started coding in the last year or so and I just learned about sorting and vectors last week and heap data structures yesterday. But I am really interested in solving this problem.
Anyway here goes I first started to solve this problem with selection sort... needless to say it took way too long.
Then I started looking into making a heap data structure that yields values sorted order,
which brought me to priority_queue
After about 9 hours of trying different methods, this is the closest I've gotten to solving the problem.
does anyone have any suggestions as to why after 25/27 test cases my code returns a wrong answer?
Here is my code :
// C++ program to use priority_queue to implement Min Heap
// for user defined class
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// User defined class, coworker
class CoworkerT
{
private:
int a;
int d;
public:
CoworkerT(int _a, int _d)
{
a = _a;
d = _d;
}
int SimAddAD() const
{
int aD;
aD = a + d;
return aD;
}
int AddAD()
{
a = a + d;
return a;
}
int getA() const {
return a;
}
int getD() const {
return d;
}
};
// To compare two coworkers possible a value
class Min
{
public:
int operator() (const CoworkerT& p1, const CoworkerT& p2)
{
return p1.SimAddAD() > p2.SimAddAD();
}
};
//compare two a values between coworkers
class Max
{
public:
int operator() (const CoworkerT& p1, const CoworkerT& p2)
{
return p1.getA() < p2.getA();
}
};
int AskForA() {
int a;
cin >> a;
return a;
}
int AskForD() {
int d;
cin >> d;
return d;
}
priority_queue <CoworkerT, vector<CoworkerT>, Max >
PopulateMax(priority_queue <CoworkerT, vector<CoworkerT>, Max > max,
priority_queue <CoworkerT, vector<CoworkerT>, Min > min) {
while (min.empty() == false)
{
CoworkerT e = min.top();
max.push(CoworkerT(e.getA(), e.getD()));
min.pop();
}
return max;
}
// Driver code
int main()
{
int h, c, i, a, d;
cin >> h >> c;
// Creates a Min heap of points (order by possible a +d combination )
priority_queue <CoworkerT, vector<CoworkerT>, Min > pq;
// Creates a Max heap of points (order by actual a value )
priority_queue <CoworkerT, vector<CoworkerT>, Max > max;
// Insert points into the min heap
for (int i = 0; i < c; i++) {
a = AskForA();
d = AskForD();
pq.push(CoworkerT(a, d));
}
i = 0;
while (i < h) {
CoworkerT e = pq.top();
a = e.AddAD();
d = e.getD();
pq.pop();
pq.push(CoworkerT(a, d));
i++;
}
max = PopulateMax(max, pq);
CoworkerT eMax = max.top();
cout << eMax.getA() << endl;
return 0;
}
I just want to say that I ended up using something similar to my original algorithm using the heap. The problem was my use of int I switched to an unsigned long long int ~(though that might have been overkill?) and it worked like a charm.
// C++ program to use priority_queue to implement Min Heap
// for user defined class
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// User defined class, coworker
class CoworkerT {
private:
unsigned long long int a;
unsigned long long int d;
public:
CoworkerT(unsigned long long int _a, unsigned long long int _d){
a = _a;
d = _d;
}
unsigned long long int SimAddAD() const{
return a + d;
}
unsigned long long int AddAD(){
return a + d;;
}
unsigned long long int getA() const {
return a;
}
unsigned long long int getD() const {
return d;
}
};
//compare two coworkers possible a + d values
struct MinSort {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.SimAddAD() < p2.SimAddAD();
}
};
//compare two coworkers possible a + d values ~for some reason heap lesser than or greater need to be reverse of operator for sort???
struct Min {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.SimAddAD() > p2.SimAddAD();
}
};
//compare two a values between coworkers
struct MaxSort {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.getA() > p2.getA();
}
};
void FindAndPrintMax(vector<CoworkerT>& max) {
sort(max.begin(), max.end(), MaxSort());
CoworkerT minMax = max.front();
cout << minMax.getA();
}
void InputCoworkersAD(vector<CoworkerT>& min, unsigned long long int& h, unsigned long long int& c) {
int a, d, i;
cin >> h >> c;
// Insert a and d into the vector
if (h <= 100000 && h >= 1 && c <= 100000 && c >= 1) {
for (i = 0; i < c; i++) {
cin >> a >> d;
min.push_back(CoworkerT(a, d));
}
}
make_heap(min.begin(), min.end(), Min());
}
void AskForHelp(vector<CoworkerT>& min, unsigned long long int h) {
int i = 0;
while (i < h) {
push_heap(min.begin(), min.end(), Min());
CoworkerT e = min.front();
pop_heap(min.begin(), min.end(), Min());
min.pop_back();
min.push_back(CoworkerT(e.AddAD(), e.getD()));
i++;
}
}
// Driver code
int main()
{
unsigned long long int h, c;
vector<CoworkerT> min;
InputCoworkersAD(min, h, c);
AskForHelp(min, h);
FindAndPrintMax(min);
return 0;
}
Just ran into these 2 Clang errors:
ld.lld: error: undefined symbol: vtable for HashFn
>>> referenced by hashFn.h:40 ......
HashFn::HashFn(int, bool)
And
ld.lld: error: undefined symbol: vtable for HashFn
>>> referenced by hashFn.h:36 ......
HashFn::HashFn(HashFn const&)
hashFn.h -->
#ifndef HASHFN_H_
#define HASHFN_H_
#include "./base.h"
typedef uint64_t uint64Array[30];
static int precomputedArraySize = sizeof(uint64Array) / sizeof(uint64_t);
inline uint64_t customPow(uint64Array *precomputedPowers, bool usePrecomputed,
uint64_t base, int exp) {
if (usePrecomputed && exp < precomputedArraySize) {
return (*precomputedPowers)[exp];
}
// TOOD: Optimization possible here when passed in toSize which is bigger
// than precomputedArraySize, we can start from the value of the last
// precomputed value.
uint64_t result = 1;
while (exp) {
if (exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
// Functor for a hashing function
// Implements a Rabin fingerprint hash function
class HashFn {
public:
// Initialize a HashFn with the prime p which is used as the base of the Rabin
// fingerprint algorithm
explicit HashFn(int p, bool precompute = true) {
this->p = p;
this->precompute = precompute;
if (precompute) {
uint64_t result = 1;
for (int i = 0; i < precomputedArraySize; i++) {
precomputedPowers[i] = result;
result *= p;
}
}
}
//virtual ~HashFn(){}
~HashFn(){}
virtual uint64_t operator()(const char *input, int len,
unsigned char lastCharCode, uint64_t lastHash);
virtual uint64_t operator()(const char *input, int len);
private:
int p;
bool precompute;
uint64Array precomputedPowers;
};
#endif // HASHFN_H_
hashFn.cc -->
#include "hashFn.h"
uint64_t HashFn::operator()(const char *input, int len,
unsigned char lastCharCode, uint64_t lastHash) {
// See the abracadabra example:
// https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
return (lastHash - lastCharCode *
customPow(&precomputedPowers, precompute, p, len - 1)) *
p + input[len - 1];
}
uint64_t HashFn::operator()(const char *input, int len) {
uint64_t total = 0;
for (int i = 0; i < len; i++) {
total += input[i] *
customPow(&precomputedPowers, precompute, p, len - i - 1);
}
return total;
}
There is already a derived class from HashFn:
class HashFn2Byte : public HashFn {
public:
HashFn2Byte() : HashFn(0, false) {
}
uint64_t operator()(const char *input, int len,
unsigned char lastCharCode, uint64_t lastHash) override;
uint64_t operator()(const char *input, int len) override;
};
......
What went wrong? I can vaguely understand this has something to do with the virtual destructor but not sure why the vtable is undefined (if I define all declarations then vtable should be there automatically?).
Also, I'm now playing in Chromium so I don't know how would the fact all files are compiled into a "jumbo" object affect the results. The standalone version of this code (a Node native module) can compile and run normally.
Any input is appreciated! Thanks.
After a bit of bug searching, I've found that my code leaves with exit code 11 at a certain point, and this is because an EXC_BAD_ACCESS error with code 1. After some googling, I see this must be due to some memory mismanagement, but I'm new to C++ and nothing seems obvious to me.
The code is exiting at the line
fieldFuncts[field](string, equal, validOps, length, difficulty, rng, opGen);
in the file (last function)
//
// Created by Anthony Monterrosa on 4/17/18.
//
#include "MathExpr.h"
#include <list>
#include <iostream>
#include <random>
std::vector<std::function<void(std::vector<MathExpr::CharType> &, MathExpr::NumType &, std::vector<MathExpr::NumType> &)>> MathExpr::layerFuncts;
std::vector<std::function<void(std::vector<MathExpr::CharType> &, MathExpr::NumType &, std::vector<MathExpr::Op> &, unsigned char, unsigned char, std::mt19937 &, std::uniform_int_distribution<MathExpr::OpType> &)>> MathExpr::fieldFuncts;
void MathExpr::init() {
initLayerFuncts();
initFieldFuncts();
}
void MathExpr::initLayerFuncts() {
layerFuncts.resize(Op::EOOE);
layerFuncts[static_cast<unsigned long>(Op::addition)] = [](std::vector<MathExpr::CharType> &string, NumType &equal, std::vector<NumType> & otherArgs) -> void {
string.insert(string.end(), {' ', opToChar(Op::addition), ' '});
equal += otherArgs[0];
std::vector<MathExpr::CharType> digits = intToDigit(otherArgs[0]);
for(int i = 0; i < digits.size(); i++ ) {
string.push_back(digits[i]);
}
};
layerFuncts[static_cast<unsigned long>(Op::subtraction)] = [](std::vector<MathExpr::CharType> &string, MathExpr::NumType &equal, std::vector<NumType> & otherArgs) -> void {
string.insert(string.end(), {' ', opToChar(Op::subtraction), ' '});
equal -= otherArgs[0];
std::vector<MathExpr::CharType> digits = intToDigit(otherArgs[0]);
for(int i = 0; i < digits.size(); i++ ) {
string.push_back(digits[i]);
}
};
}
void MathExpr::initFieldFuncts() {
fieldFuncts.resize(Field::EOFE);
fieldFuncts[static_cast<unsigned long>(Field::integers)] = [](std::vector<MathExpr::CharType> &string, NumType &equal, std::vector<MathExpr::Op> &validOps, unsigned char length, unsigned char difficulty, std::mt19937 &rng, std::uniform_int_distribution<MathExpr::OpType> &opGen) -> void {
std::uniform_int_distribution<MathExpr::NumType> numGen(1, static_cast<MathExpr::NumType>(pow(10, difficulty)));
equal = numGen(rng);
std::vector<MathExpr::CharType> digits = intToDigit(equal);
for(int i = 0; i < digits.size(); i++ ) {
string.push_back(digits[i]);
}
for (int i = 0; i < length - 1; i++) {
MathExpr::Op op = validOps[opGen(rng)];
int count = otherArgsCount(op);
std::vector<MathExpr::NumType> otherArgs(count);
for(int j = 0; j < count; j++) {
otherArgs[j] = (numGen(rng));
}
layer(string, equal, op, otherArgs);
}
};
}
char MathExpr::opToChar(OpType ordinal) {
return opToChar(static_cast<Op>(ordinal));
}
char MathExpr::opToChar(Op op) {
switch(op) {
case Op::addition : return '+';
case Op::subtraction : return '-';
default : return '_';
}
}
MathExpr::NumType MathExpr::otherArgsCount(MathExpr::Op op) {
switch(op) {
case Op::addition : return 1;
case Op::subtraction : return 1;
default : return 0;
}
}
std::vector<MathExpr::CharType> MathExpr::intToDigit(MathExpr::NumType num) {
std::vector<MathExpr::CharType> digits;
while(num >= 10) {
digits.insert(digits.begin(),'0' + static_cast<MathExpr::CharType>(num % 10));
num /= 10;
} digits.insert(digits.begin(), '0' + static_cast<MathExpr::CharType>(num));
return digits;
}
bool MathExpr::initBool = false;
MathExpr::MathExpr(std::vector<CharType> exp, MathExpr::NumType equal) {
if(!initBool) init();
this->string = std::vector<CharType>(exp);
this->equal = equal;
}
void MathExpr::print(MathExpr &exp) {
for(int i = 0; i < exp.string.size(); i++) {
std::cout << exp.string[i];
}
}
void MathExpr::layer(std::vector<MathExpr::CharType> &string, MathExpr::NumType &equal, MathExpr::Op op, std::vector<MathExpr::NumType> &otherArgs) {
layerFuncts[op](string, equal, otherArgs);
}
MathExpr MathExpr::generate(std::vector<MathExpr::Op> &validOps, MathExpr::Field field, unsigned char length, unsigned char difficulty) {
std::vector<MathExpr::CharType> string;
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<MathExpr::OpType> opGen(0, static_cast<MathExpr::OpType>(validOps.size() - 1));
MathExpr::NumType equal;
fieldFuncts[field](string, equal, validOps, length, difficulty, rng, opGen);
return MathExpr::MathExpr(string, equal);
}
here is the corresponding .h file
//
// Created by Anthony Monterrosa on 4/17/18.
//
// EO_E -> "end of _ enum".
#ifndef MATHTESTGENERATOR_MATHEXPR_H
#define MATHTESTGENERATOR_MATHEXPR_H
#include <functional>
#include <random>
#include <vector>
class MathExpr {
public:
using FieldType = unsigned char;
using OpType = unsigned char;
using NumType = short int;
using CharType = char;
enum Field : FieldType {
integers,
EOFE // rational, real, complex.
};
enum Op : OpType {
addition,
subtraction,
EOOE // multiplication, division, absolute value, radical
};
explicit MathExpr(std::vector<CharType>, NumType);
std::vector<CharType> string;
NumType equal;
static void print(MathExpr &);
static MathExpr generate(std::vector<Op> &, Field = Field::integers, unsigned char length = 2, unsigned char difficulty = 1);
//protected:
static void init();
static bool initBool;
static void layer(std::vector<MathExpr::CharType> &, NumType &, Op, std::vector<NumType> &);
static NumType otherArgsCount(Op);
static std::vector<CharType> intToDigit(NumType);
static char opToChar(OpType);
static char opToChar(Op);
static std::vector<std::function<void(std::vector<MathExpr::CharType> &, NumType &, std::vector<NumType> &)>> layerFuncts;
static void initLayerFuncts();
static std::vector<std::function<void(std::vector<MathExpr::CharType> &, NumType &, std::vector<MathExpr::Op> &, unsigned char, unsigned char, std::mt19937 &, std::uniform_int_distribution<MathExpr::OpType> &)>> fieldFuncts;
static void initFieldFuncts();
};
#endif //MATHTESTGENERATOR_MATHEXPR_H
My gut says the error has to do with the "string" vector, but I'm unsure of how to tell. I would appreciate insight into the problem.
I am writing to perform and test a binary search. The aim is to get the maximum x when y<=0 for the function y=x-1, and the search range is [-2,2),obviously the answer should be 1.
for test part, I should test if the invocations of function f is less than the calculated max_invoke
a segmentation fault appeared, and when I valgrind it, the error is:
==126667== Use of uninitialised value of size 8
==126667== at 0x400C8A: binarySearchForZero(Function<int, int>*, int,
int) (in /home/jw562/ece551/092_tests_binsrch/test)
==126667== by 0x400DD5: check(Function<int, int>*, int, int, int,
char const*) (in /home/jw562/ece551/092_tests_binsrch/test)
==126667== by 0x400E81: main (in
/home/jw562/ece551/092_tests_binsrch/test)
==126667== Uninitialised value was created by a stack allocation
==126667== at 0x400E41: main (in
/home/jw562/ece551/092_tests_binsrch/test)
below is my code:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
template<typename R, typename A>
class Function {
public:
virtual R invoke(A arg) = 0;
virtual ~Function() {}
};
class CountedIntFn : public Function<int,int>{
protected:
unsigned remaining;
Function<int,int> * f;
const char * mesg;
public:
CountedIntFn(unsigned n, Function<int,int> * fn, const char * m):
remaining(n),f(fn),mesg(m) {}
virtual int invoke(int arg) {
if (remaining == 0) {
fprintf(stderr,"Too many function invocations in %s\n", mesg);
exit(EXIT_FAILURE);
}
remaining--;
return f->invoke(arg);
}
class linearFunction : public Function<int, int> {
public:
virtual int invoke(int arg) {
int ans = arg-1;
return ans;
}
virtual ~linearFunction(){}
};
int binarySearchForZero(Function<int, int> * f, int low, int high){
if (high <= low){
cout << "high less or equal than low" << endl;
return EXIT_FAILURE;
}
int low_ans = f->invoke(low);
int high_ans = f->invoke(high);
int mid = (high-low)/2+low;
int mid_ans = f->invoke(mid);
if (low_ans > 0){
return low;//all positive
}
if (high_ans < 0){
return high-1;//all negtive
}
if (low_ans = high_ans){
return low;//all zero
}
if (mid_ans <= 0){
low = mid;
}
if (mid_ans >= 0){
high = mid;
}
return binarySearchForZero(f,low,high);
}
void check(Function<int,int> * f,int low,int high,int
expected_ans,const char * mesg){
int max_invoke = 0;//the maximum number of invocations allowed
if (high > low){
max_invoke = (int)(log2(high-low))+1;
}
else {
max_invoke = 1;
}
CountedIntFn count(max_invoke,f,mesg);
int ans = binarySearchForZero(f,low,high);
if (ans != expected_ans){
cout << "wrong answer" <<endl;
}
}
int main(void){
linearFunction *fl;
const char * message = "linearFunction";
int low = -2;
int high = 2;
int expected_ans = 1;
check(fl,low,high,expected_ans,message);
return EXIT_SUCCESS;
}
This is because variable fl of type linearFunction* is uninitialized.
You can change it to a non-pointer, and invoke with address-of operator:
linearFunction fl;
...
check(&fl, low, high, expected_ans, message);
There is some linking error here. I looked for that online, yet still I couldn't find the problem. How can I fix it?
g++ test.cpp -o test
/tmp/ccDfCj4N.o: In function `Interval::Interval()':
test.cpp:(.text._ZN8IntervalC2Ev[Interval::Interval()]+0x9): undefined reference to `vtable for Interval'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD0Ev[IntInterval::~IntInterval()]+0x1d): undefined reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD1Ev[IntInterval::~IntInterval()]+0x1d): undefined reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o:(.rodata._ZTI11IntInterval[typeinfo for IntInterval]+0x10): undefined reference to `typeinfo for Interval'
collect2: ld returned 1 exit status
Here is the code!
All classes are in a same file for a pilot program.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
#define MAX_IP_RANGE 4294967295
class Interval {
public:
virtual Interval * interval_copy() = 0;
virtual unsigned long get_begin() = 0;
virtual unsigned long get_end() = 0;
virtual unsigned long get_length() = 0;
virtual Interval* get_intersect(Interval *interval) = 0; // Examine whether two intervals have intersection
virtual Interval* copy() = 0;
virtual ~Interval();
virtual bool is_equal(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 == b2 && e1 == e2)
return true;
return false;
}
virtual bool is_within(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 >= b2 && e1 <= e2)
return true;
return false;
}
virtual bool contains(Interval *interval) { // Examine whether this interval contains another interval
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 <= b2 && e1 >= e2)
return true;
return false;
}
virtual bool is_empty() {
return (get_end()<get_begin())?true:false;
}
virtual bool is_intersect(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1>e2)
return false;
if (b2>e1)
return false;
return true;
}
virtual void print()
{
cout << '('<<get_begin() << ',' << get_end() << ")\n";
}
};
class IntInterval : public Interval {
private:
unsigned long begin;
unsigned long end;
IntInterval();
public:
virtual Interval * interval_copy() {
return new IntInterval(begin, end);
}
IntInterval(unsigned long a, unsigned long b): begin (a), end (b)
{}
void set_value(unsigned long a, unsigned long b) {
begin = a;
end = b;
}
void set_begin(unsigned long a) {
begin = a;
}
void set_end(unsigned long b) {
end = b;
}
virtual Interval* copy()
{
Interval *new_interval = new IntInterval(begin, end);
return new_interval;
}
virtual unsigned long get_begin() {
return begin;
}
virtual unsigned long get_length() {
return end-begin+1;
}
virtual unsigned long get_end() {
return end;
}
virtual Interval* get_intersect(Interval *interval); // Get the intersect part of two intervals
virtual ~IntInterval() {};
};
Interval* IntInterval::get_intersect(Interval *interval) {
unsigned long begin2 = interval->get_begin();
unsigned long end2 = interval->get_end();
if (end < begin2 || begin > end2) {
return new IntInterval(1, 0);
}
return new IntInterval((begin>begin2)?begin:begin2, (end<end2)?end:end2);
}
IntInterval * parse_ip(const char * _str) {
unsigned long _begin=0;
unsigned long _end=0;
string input(_str);
if (input.find('-') != string::npos){
string begin = input.substr(0, input.find('-'));
string end = input.substr(input.find('-')+1);
unsigned int ip1 = 0, ip2 = 0;
unsigned int ip3 = 0, ip4 = 0;
sscanf(begin.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
_begin = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
ip1 = 0; ip2 = 0; ip3 = 0; ip4 = 0;
sscanf(end.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
_end = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
if ((_begin > _end) || (_end > MAX_IP_RANGE)){
cout<<"ERROR: The IP INTERVAL IS WRONG The range is "<<begin<<"-"<<end<<endl;
exit(0);
}
}
return new IntInterval(_begin, _end);
}
bool compFunc (Interval * i, Interval * j) {
return (i->get_begin() < j->get_begin());
}
int main () {
vector <vector<pair<string, string> > > nets;
vector<pair<string, string> > x;
vector<pair<string, string> > y;
x.push_back(make_pair("1.1.1.1", "3.0.0.0"));
x.push_back(make_pair("10.2.5.3", "30.2.5.0"));
x.push_back(make_pair("100.2.25.2", "130.2.25.2"));
y.push_back(make_pair("41.0.2.2", "43.2.2.5"));
y.push_back(make_pair("131.2.2.2", "135.5.5.2"));
nets.push_back(x);
nets.push_back(y);
vector <IntInterval *> _nets;
for (int i=0; i<(int)nets.size(); i++)
for(int j=0; j<(int)nets[i].size(); j++) {
string s = nets[i][j].first + '-' + nets[i][j].second;
_nets.push_back(parse_ip(s.c_str()));
}
sort(_nets.begin(), _nets.end(), compFunc);
if (_nets.size()>1)
for (vector<IntInterval *>::iterator it = _nets.begin()+1; it < _nets.end(); ) {
if ((*it)->get_begin()-1 == (*(it-1))->get_end()) {
(*(it-1))->set_end((*it)->get_end());
_nets.erase(it);
}
else if ((*it)->get_begin()-1 < (*(it-1))->get_end()) {
it++;
cout<<"ERROR: Network address overlapping!"<<endl;
}
else
it++;
}
for (int i=0; i<(int)_nets.size(); i++)
cout << _nets[i]->get_begin() << " " << _nets[i]->get_end() << endl;
return 0;
}
You never provided an implementation for virtual ~Interval(); and several other functions. You must provide an implementation for all non-pure virtual functions you declare. In particular, G++ emits the vtable along with the implementation of the first-declared non-inline function in a class. Omitting its implementation means you won't have a vtable, and thus won't be able to construct the class (hence these errors).
In short, define every function you declare, except for pure virtuals. There are some cases where it's justified to leave out the definition for a declared function, but they are very rare.
I had the same problem. I was merging my code with upstream changes and picked my change over another engineer's seemingly identical change in the header file. It just turned out that they had changed the constness of the method and I hadn't noticed, and you will get this error for the reason #bdonian says.
virtual void foo(Many params, As part, Of veryLong, Method signature);
and theirs:
virtual void foo(Many params, As part, Of veryLong, Method signature) const;
When merging I picked the first version, but the implementation had the second one, resulting in the compiler assuming there is an overload of foo() that is undefined, and hence the error.
In virtual classes never put undefined functions first. Move
IntInterval();
to after the first defined function:
private:
unsigned long begin;
unsigned long end;
public:
virtual Interval * interval_copy(){return new IntInterval(begin,end);}
IntInterval(unsigned long a,unsigned long b): begin (a),
end (b)
{}
private:
IntInterval();
public:
It's because C++ glues the vtable to the first function. If you don't define it, the vtable will be undefined as well.
As mentioned by other answers, you need to also define the destructor:
public:
virtual ~IntInterval()
{
// Destruction code
}