错误:请求成员...这是非类型的

时间:2013-09-14 20:49:57

标签: c++

我意识到错误来自于在自定义类中使用向量,但我一直在努力解决它们。如何在类对象的一部分调用向量方法?

这些是我得到的错误:

Word.cpp: In member function ‘void Word::addPosition(int)’:
Word.cpp:20: error: request for member ‘push_back’ in ‘((Word*)this)->Word::positions’, which is of non-class type ‘std::vector<int, std::allocator<int> >*’
Word.cpp: In member function ‘int Word::getPosition(int)’:
Word.cpp:26: error: request for member ‘size’ in ‘((Word*)this)->Word::positions’, which is of non-class type ‘std::vector<int, std::allocator<int> >*’
Word.cpp:27: error: request for member ‘size’ in ‘((Word*)this)->Word::positions’, which is of non-class type ‘std::vector<int, std::allocator<int> >*’
Word.cpp:29: error: cannot convert ‘std::vector<int, std::allocator<int> >’ to ‘int’ in return

标题

#pragma once
#include <string>
#include <vector>

class Word {
  public:
    Word();
    ~Word();
    void setWord(std::string);
    void addPosition(int);
    std::string getWord();
    int getPosition(int);
  private:
    std::string word;
    std::vector<int> *positions;
};

实施

#include "Word.h"
#include <string>
#include <vector>

Word::Word() {
    this->word = "";
    this->positions = new std::vector<int>(5);
}

void Word::setWord(std::string s) {
    this->word = s;
}

void Word::addPosition(int i) {
    this->positions.push_back(i);
}

std::string Word::getWord() {
    return this->word;
}

int Word::getPosition(int i) {
    if (i < this->positions.size() && i > 0) {
        for (int j = 0; j < this->positions.size(); i++) {
            if (i == j) {
                return positions[j];
            }
        }
    }
    return -1;
}

编辑:这是设置课程的更好方法吗? 标题:

    #pragma once
    #include <string>
    #include <vector>

    class Word {
      public:
        Word();
        ~Word();
        void setWord(std::string);
        void addPosition(int);
        std::string getWord();
        int getPosition(int);
      private:
        std::string word;
        std::vector<int> positions;
    };

实施:

Word::Word(){
    word = "";
}

void Word::setWord(std::string s){
    this -> word = s;
}
void Word::addPosition(int i){
    this -> positions.push_back(i);
}
std::string Word::getWord(){
    return this -> word;
}
int Word::getPosition(int i){
    if (i < this -> positions.size() && i > 0) {
        for (int j = 0; j<this -> positions.size(); i++) {
            if (i == j) {
                return (this->positions)[j];
            }
        }
    }
    return -1;
}

但现在我收到了这个错误:

Undefined symbols for architecture x86_64:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

5 个答案:

答案 0 :(得分:9)

除了@Chris的答案之外,这里的事实上的问题是你正在使用指向矢量而不是矢量的指针
没有理由动态分配向量,因为它在内部使用动态内存来存储其元素。向量的优点是它管理自己的内存,并在其范围的末尾释放它的内存:那就是RAII

我个人推荐Going Native 2013 Stroupstrup talk "The Essence of C++"。他提供了有关C ++中数据管理的相关示例和解释:数据与数据处理程序。

对于那些来自Java的人:关于Java和C ++中的内存管理的观点

在Java中,我们区分两种数据:基本类型(Ints,chars,booleans等)和对象(类的实例)。 Java通过垃圾收集器管理其内存:Java运行时(JVM)分配堆上对象使用的内存,为您提供的是指向该分配对象的指针。所以在Java中,你的变量实际上是指向分配对象的堆内存的堆栈上分配的指针(这与the usual problems which noobs have with Java pass by value直接相关)。这允许Java轻松地共享对象实例的所有权:它只跟踪(通过引用计数)有多少变量引用特定对象 垃圾收集器偶尔会查看程序堆并释放引用计数已降至零的对象使用的内存(即,您尚未使用的对象)。因此,正如您所看到的, GC提供了一种非确定性的方式来释放/管理内存

C ++内存管理被分配为以确定的方式 。所有变量都在特定范围内声明,确定其生命周期当变量的范围结束时,该变量的生命周期结束,对于对象,其析构函数调用为执行适当的释放操作 这称为资源获取是初始化,或RAII。

RAII表示对象管理资源(内存,文件句柄,网络端口等),并且该资源的获取,使用和发布直接链接到管理资源的对象的生命周期。这提供了一个确定且无泄漏的系统来管理资源:请注意,“资源”不仅指内存,而是垃圾收集器管理的唯一资源。在99%的案例中,RAII比垃圾收集器更强大,更安全。

std::vector是通过RAII管理资源(在其情况下是动态分配的可调整大小的数组)的类的典型示例。
正如您所看到的,我根本没有谈论指针:必须使用指针来共享对象的所有权,或者分配内存的动态块(数组)。但请注意,第一种情况可能是(并且必须)通过smart pointers实现,第二种情况可以通过基于RAII的容器实现,例如std::vector

使用指针动态分配std::vector的问题是:

  • std::vector在内部管理一个动态数组,它在那里分配元素,所以std::vector大小(也就是说,什么向量适合堆栈)只有指针的指针大小数组和两个计数器(整数)。不要担心堆栈中向量的大小(由于可能的堆栈溢出):数组在堆上分配。

  • 使用指针动态分配向量会破坏RAII,因为向量实例的生命周期未链接到任何范围,其生命周期必须由您确定,当您决定解除分配(delete)向量。当然手动动态内存管理容易出错。

同样,我建议你观看Stroupstrup的演讲:他比我解释得更好:)

答案 1 :(得分:4)

positions是一个指针。您需要取消引用它才能到达基本向量:

this->positions->size();

通常,您获得的错误是由于无法解除引用(因为T*不是类类型;它是指针,而指针是基本类型)。

答案 2 :(得分:2)

positions是一个指针,所以你需要使用间接:

this->positions->push_back(i);

在这种情况下不要使用指针。你最好使用堆栈分配的向量并通过构造函数初始化它:

class Word
{
    ...
private:
    std::string word;
    std::vector<int> positions;
};

Word::Word()
    : word(""), positions(5) { }

void Word::addPosition(int i)
{
    this->positions.push_back(i);
}

答案 3 :(得分:1)

positions是指向向量的指针,用法应该是->运算符:

另外,请注意我更改了return positions[j];

#include "Word.h"
#include <string>
#include <vector>
Word::Word(){
    this -> word = "";
    this -> positions = new std::vector<int>(5);
}

void Word::setWord(std::string s){
    this -> word = s;
}
void Word::addPosition(int i){
    this -> positions->push_back(i);
}
std::string Word::getWord(){
    return this -> word;
}
int Word::getPosition(int i){
    if (i < this -> positions.size() && i > 0) {
        for (int j = 0; j<this -> positions->size(); i++) {
            if (i == j) {
                return (*positions)[j];
            }
        }
    }
    return -1;
}

另一个解决方案是,不要按住指针,定义像这样的矢量:

private:
    std::string word;
    std::vector<int> positions;

然后您还应删除此行this -> positions = new std::vector<int>(5); 您还应该知道向量在需要时会自动扩大,如果它很小,您不需要指定它的初始大小(您应该考虑将其用于真正的大值)

答案 4 :(得分:1)

positions是指针,因此您需要positions->push_back

另一方面,为什么要在堆上分配向量?它可以是该类的成员。