![](/img/trans.png)
[英]std::vector vs std::initializer_list issue: undefined bahevior
[英]C++ undefined reference to `Vector_container::Vector_container(std::initializer_list<double>)'
我正在尝试从A Tour of C ++ (第4.3章)中编译代码,该代码描述了“抽象类型”。 但是,我收到一个编译器错误:
$ g++ -std=c++11 abstract.cpp Vector.cpp Vector_container.cpp
/tmp/ccToFsNS.o: In function `g()':
abstract.cpp:(.text+0x9c): undefined reference to `Vector_container::Vector_container(std::initializer_list<double>)'
abstract.cpp:(.text+0xb4): undefined reference to `Vector_container::~Vector_container()'
abstract.cpp:(.text+0xc5): undefined reference to `Vector_container::~Vector_container()'
collect2: error: ld returned 1 exit status
如何修复我的代码以便编译? 我是C ++的新手,我正尽我所能尝试翻译Stroustrup的示例。
abstract.cpp:
#include "Vector_container.hpp"
#include <iostream>
void use(Container& c)
{
const int sz = c.size();
for (auto i = 0; i != sz; ++i)
{
std::cout << c[i] << "\n";
}
}
void g()
{
Vector_container vc {10, 9, 8, 7, 6};
use(vc);
}
int main()
{
g();
}
Vector_container.hpp:
#include "Container.hpp"
#include "Vector.hpp"
#include <initializer_list>
#pragma once
class Vector_container : public Container {
Vector v;
public:
Vector_container(int);
Vector_container(std::initializer_list<double>);
~Vector_container();
double& operator[](int);
int size() const;
};
Vector_container.cpp:
#include "Container.hpp"
#include "Vector.hpp"
class Vector_container : public Container {
Vector v;
public:
Vector_container(int s) : v(s) {}
Vector_container(std::initializer_list<double> lst) : v{lst} {}
~Vector_container() {}
double& operator[](int i) { return v[i]; }
int size() const { return v.size(); }
};
container.hpp:
#pragma once
class Container {
public:
virtual double& operator[](int) = 0;
virtual int size() const = 0;
virtual ~Container() {}
};
Vector.hpp:
#include <initializer_list>
#pragma once
class Vector {
public:
Vector(int);
Vector(std::initializer_list<double>);
~Vector();
double& operator[](int);
int size() const;
void push_back(double);
private:
double* elem;
int sz;
};
Vector.cpp:
#include "Vector.hpp"
#include <stdexcept>
Vector::Vector(int s) : elem{new double[s]}, sz{s}
{
if (s < 0)
{
throw std::length_error{"Size must be >= 0"};
}
for (auto i = 0; i != s; ++i)
{
elem[i] = 0;
}
}
Vector::Vector(std::initializer_list<double> lst)
: elem{new double[lst.size()]}, sz{static_cast<int>(lst.size())}
{
std::copy(lst.begin(), lst.end(), elem);
}
Vector::~Vector() {
delete[] elem;
}
double& Vector::operator[](int i)
{
if (i < 0 || size() <= i)
{
throw std::out_of_range{"Vector::operator[]"};
}
return elem[i];
}
int Vector::size() const
{
return sz;
}
正如评论员和Sam指出的那样,我没有正确定义Vector_container
。 我将Vector_container.cpp更改为:
#include "Vector_container.hpp"
Vector_container::Vector_container(int s) : v(s) {}
Vector_container::Vector_container(std::initializer_list<double> lst) : v{lst} {}
Vector_container::~Vector_container() {}
double& Vector_container::operator[](int i)
{
return v[i];
}
int Vector_container::size() const
{
return v.size();
}
现在,程序可以按预期进行编译和运行。
我还没有读过这本书,但是得知Stroustrup会写一些东西,我会感到很惊讶:
1)明确取决于gcc特定的编译指示,并且
2)鼓励#pragma once
滥用#pragma once
3)提供了一种在头文件中声明类的不良做法的示例,然后在完全不包含头文件的完全独立的转换单元中定义类的方法。
只需完全摆脱Vector_container.hpp
,然后将Vector_container.cpp
重命名为Vector_container.hpp
,代码就可以编译和链接。
您的问题是,现有Vector_container.cpp
转换单元中的任何内容实际上都不会最终实例化并编译类方法,以便链接程序从其他转换单元中查找和解析引用。
您也可以用非内联定义替换Vector_container.cpp
的内联定义。 这也会实例化它们。 但这对Vector_container.hpp
的重复定义没有任何Vector_container.hpp
,我认为这是非常糟糕的做法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.