簡體   English   中英

C ++對`Vector_container :: Vector_container(std :: initializer_list的未定義引用) <double> )&#39;

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM