2015-04-30 4 views
-1

Итак, вот мой код:C++ ошибка: неизвестный тип имя

/**************************************************************** 
File:    Video.h 
Description:  class declarations 

Author:   David && Evan 
Class:   CSCI 120 
Date:    2015 May 13 

We hereby certify that this program is entirely our own work. 
*****************************************************************/ 

#ifndef VIDEO_H 
#define VIDEO_H 

#include <iostream> 
#include <string> 
#include <vector> 

#include "Person.h" 
#include "Date.h" 

using namespace std; 

enum kind {MOVIE, TELEVISION, COMPUTER}; 
// 'MOVIE' = standalone film of any length, whether it's part of a franchise or not 
// 'TELEVISION' = episode from mini- or recurring series 
// 'COMPUTER' = online or locally hosted files 
/* If need be, we can extend this by adding something for analog home movies, 
i.e., camcorder tapes or 8mm film. */ 

namespace Vids 
{ 

    class Video{ 

     public: 
      Video(); // default constructor 
      Video(string name, string audience, string location, vector<Person> directors, 
       vector<Person> actors, Date released); 
      virtual void display() = 0; // displays information for all objects of Video type 
      virtual void displayAll() = 0; // displays all information for one object 
      unsigned char getDirectorSize() const { return directorSize; } 
      unsigned char getActorSize() const { return actorSize; } 
      string getName() const { return name; } 
      string getAudience() const { return audience; } 
      string getLocation() const { return location; } 
      Date getReleased() const { return released; } 
      Date getViewed() const { return viewed; } 
      string Truncate(string str, size_t width) { // shortens output 
       if (str.length() > width) 
        return str.substr(0, width) + "..."; 
       return str; 
      } // truncate 

     protected: 
      short runtimeMinutes; 
      /* Theoretically runtime could be unsigned, but we might eventually 
      need negatives for special values. I doubt we'll see one needing 
      more than 32K minutes, so no worry about overflow. */ 
      unsigned char directorSize; 
      // number of elements in each vector, shouldn't need more than 255 
      unsigned char actorSize; 
      string name; // title of movie 
      string audience; // PG = "Plenty Guns", PG-13 = "13 or more guns" 
      string location; 
      /* Location is a catch-all field for: URL, shelf disc is on, format 
      type, name of person it is loaned to, etc. */ 
      vector<Person> directors(directorSize); 
      /* David: I considered using other containers, but none of them 
      offered any obvious benefits over the vector. */ 
      vector<Person> actors(actorSize); 
      Date released; 
      Date viewed; 
      /* 'viewed' can be used to answer the question: "What haven't i 
      watched lately?" */ 

    }; // end class Video 

} // end namespace Vids 

#endif 

и компиляции [с несколькими другими файлами] дает мне это:

$ g++ *.cpp -o Project3 

In file included from Computer.cpp:12: 
In file included from ./Computer.h:15: 
./Video.h:68:29: error: unknown type name 'directorSize' 
vector<Person> directors(directorSize); 
         ^
./Video.h:71:26: error: unknown type name 'actorSize' 
vector<Person> actors(actorSize); 
        ^

directorSize объявляется в том же объеме, как и директоров , так почему компилятор не распознает его?

+0

'directorSize' - это имя параметра, а не имя типа. Кроме того, вы объявляете это как метод, а не полем. Если вы хотите объявить его как поле, не используйте круглые скобки и не инициализируйте его в другом месте. – huu

+3

Этот размер относится к списку инициализаторов членов, а не к объявлениям членов класса. И, честно говоря, это слишком просто не понадобится в списке участников, глядя на ваши конструкторы. Идентичная проблема с «актерами» (но вы, вероятно, уже знали это). – WhozCraig

+0

Добро пожаловать в переполнение стека. Обычно, когда вы размещаете здесь вопрос, вы должны попытаться опубликовать «Короткий, самосохраненный, правильный (компилятивный) пример», (http://sscce.org/) или как можно ближе. Если бы вы потратили время, чтобы попытаться предоставить его здесь, вы бы сами ответили на вопрос. – kfsone

ответ

3

Линия

vector<Person> directors(directorSize); 

не правильный синтаксис для объявления переменной-члена.

Изменить его

vector<Person> directors; 

Аналогично, изменение

vector<Person> actors(actorSize); 

в

vector<Person> actors; 

Учитывая, что вы можете получить количество элементов в vector путем вызова функции size() члена , вам не нужны переменные-члены:

unsigned char directorSize; 
unsigned char actorSize; 

Удалить их.

2

Ну, этот комментарий озадачивает:

/* Theoretically runtime could be unsigned, but we might eventually 
     need negatives for special values. I doubt we'll see one needing 
     more than 32K minutes, so no worry about overflow. */ 
     unsigned char directorSize; 

unsigned char исчерпан на 255, так что если вам нужно до 32К, то вам придется использовать другой тип. На самом деле было бы лучше полностью удалить эту переменную и получить размер, выполнив directors.size() по мере необходимости.

можно инициализировать вектор в определении класса:

vector<Person> directors{directorSize}; 

Однако это может привести к непредсказуемому поведению, если бы не инициализируется directorSize в списке конструктора инициализатора (потому что вы будете использовать неинициализированные переменный directorSize).

Было бы гораздо лучше, чтобы изменить это:

vector<Person> directors; 

и предположительно в списке Конструктор инициализатора или конструктор тела, вы будете добавить некоторые элементы в этом векторе.

+0

Вы уверены, что список инициализаторов предшествует инициализации в объявлениях? Я понятия не имею, поэтому я всегда избегал этого. –

+1

Объекты @MooingDuck инициализируются в том же порядке, в котором они всегда были (базовые классы, затем члены в порядке объявления и т. Д.) Инициализатор не оценивается до инициализации объекта, который инициализируется –

0

Я покажу вашу проблему до тривиального случая, чтобы продемонстрировать проблему, наряду с применением префикса переменной «m_», популярного среди некоторых инженеров, для выделения переменной, которая является «членом» чего-то.

#include <vector> 

class Class { 
protected: 
    unsigned char m_directorSize; 
    std::vector<int> m_directors(m_directorSize); 
}; 

int main() 
{ 
    Class x; 
} 

Это не компилируется http://ideone.com/VJck4Q и изолируя проблему, мы узнали много.

Строка кода:

std::vector<int> m_directors(m_directorSize); 

Посмотрите на синтаксис этого

/typename/ /name/ (/values/); 

компилятор считает, что это член-функция декларации, поэтому она ожидает типа:

std::vector<int> something(unsigned char directorSize); 

будет объявлять функцию-член, называемую «что-то», которая принимает параметр, DirectorSize, типа unsigned char. Кстати: unsigned char почти гарантированно является 8-битным значением, способным хранить от 0 до 255. Это ужасный выбор для переменной размера. Существует стандартный тип, size_t для хранения неотрицательных размеров и ssize_t для хранения подписанных размеров.

Непонятно, почему вы считаете, что вам следует передавать директиву в вектор, но вы не можете объявить членом с вызовом функции.

Если вы хотите сформировать поведение объекта по умолчанию во время построения вашего класса, вам нужно использовать конструктор (или использовать C++ 11/C++ 14, но мы не знаем, повторно это делать):

class Foo_Sized { 
    std::vector<int> m_vec; 
public: 
    Foo() : m_vec(250) // default construct 250 elements 
    {} 
}; 

Если вы используете C++ 11/14:

class Foo_Sized { 
    std::vector<int> m_vec = std::vector<int>(250); 
}; 

Но если вы хотите повлиять на одного члена на основе значения другого, единственное место, где вы можете то есть в функции-члене, поэтому в этом случае это означает конструктор.

Если вы собираетесь создать статический массив как это, вы, вероятно, хотите использовать std::array вместо std::vector - вся суть vector в том, что она может расти динамически.

std::array<int, 250> m_arr; 

Это объявляет массив целых чисел, который имеет емкость 250 и имеет фиксированный размер. Это быстрее, чем вектор, но он всегда 250 больших. Затем вам придется отслеживать счет «использования» и другие управленческие издержки самостоятельно.

std::vector<int> vec; 
std::cout << vec.size() << '\n'; // prints 0 
vec.push(10); // add a value of 10 to the vector. 
vec.push(20); // vec is now { 10, 20 } 
std::cout << vec.size() << '\n'; // prints 2 
vec.push(30); // vec is now { 10, 20, 30 } 
std::cout << vec.size() << '\n'; // prints 3 
std::cout << vec[0] << '\n'; // prints 10 
std::cout << vec[3] << '\n'; // undefined behavior, there is no 3rd element 

std::array<int, 3> arr; 
std::cout << arr.size() << '\n'; // prints 3: fixed size. 
arr[0] = 10;      // can't push, fixed size. 
arr[1] = 20; 
std::cout << arr.size() << '\n'; // still 3, always will be. 
arr[2] = 30; 
std::cout << arr.size() << '\n'; // still 3, always will be. 
std::cout << arr[0] << '\n';  // prints 10 
std::cout << arr[3] << '\n';  // compile error: outside fixed size 

Если вы волновались о распределении памяти, можно сказать, вектор выделить авансом памяти, как это:

class Foo_Reserved { 
    std::vector<int> m_vec; 
public: 
    Foo() : m_vec()  // default construct empty 
    { 
     m_vec.reserve(250); // reserve memory for 250 elements 
    } 
}; 

Есть множество других проблем с вашим кодом, но они не являются напрямую связанный с вашим вопросом, поэтому я не собираюсь обращаться к ним/выделять их.

Но с точки зрения решения вопросов, связанных с режимом Directorize, вам следует рассмотреть возможность предоставления аксессуаров, которые запрашивают вектор или выставляют ссылку на const для вектора (это несколько разрушает инкапсуляцию, поскольку позволяет внешним вызывающим пользователям писать код на основе предположений о ваша внутренняя структура).

class Foo { 
public: 
    using vec_t = std::vector<int>; 
protected: 
    vec_t m_vec; 
public: 
    Foo() : m_vec()  // default construct empty 
    { 
    } 

    size_t vecSize() const { return m_vec.size(); } 
    // or, return a look-don't-touch reference to the vector 
    const vec_t& getVec() const { return m_vec; } 
}; 

Foo f{}; // C++14 initializer 
f.vecSize(); 
f.getVec().size();