简体   繁体   中英

C++ error: unknown type name

So, here's my code:

/****************************************************************
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

And compiling [with several other files] gives me this:

$ 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 is declared in the same scope as directors, so why is the compiler not recognizing it?

The line

vector<Person> directors(directorSize);

is not the right syntax for declaring a member variable.

Change it to

vector<Person> directors;

Similarly, change

vector<Person> actors(actorSize);

to

vector<Person> actors;

Given that you can get the number of items in a vector by calling the size() member function, you don't need the member variables:

unsigned char directorSize;
unsigned char actorSize;

Remove them.

Well, this comment is puzzling:

/* 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 maxes out at 255 so if you need up to 32K then you will have to use a different type. In fact it would be better to remove this variable entirely, and retrieve the size by doing directors.size() as needed.

It is possible to initialize the vector in the class definition:

vector<Person> directors{directorSize};

However this would cause undefined behaviour if you hadn't initialized directorSize in the constructor initializer list (because you would be using an uninitialized variable directorSize ).

It would be much better to change this to:

vector<Person> directors;

and presumably in your constructor initializer list, or constructor body, you will add some items into this vector.

I'll boil your problem down to a trivial case to demonstrate the problem, along with applying the "m_" member variable prefix popular among some engineers for highlighting a variable that is a "member" of something.

#include <vector>

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

int main()
{
    Class x;
}

This does not compile http://ideone.com/VJck4Q and by isolating the problem, we learned a lot.

The line of code:

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

Look at the syntax of this

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

The compiler thinks this is a member-function declaration, which is why it is expecting a type:

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

would declare a member-function called "something" that takes a parameter, directorSize, of type unsigned char . Incidentally: unsigned char is almost guaranteed to be an 8-bit value, capable of storing 0 through 255. That's a terrible choice for a size variable. There is a standard type, size_t for storing non-negative sizes and ssize_t for storing signed sizes.

It's unclear why you think you should be passing directorSize to the vector, but you can't declare a member with a function call.

If you want to shape the default behavior of an object at construction time of your class, you need to use a constructor (or use C++11/C++14, but we don't know if you're doing that):

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

If you were using C++11/14:

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

But if you want to affect one member based on the value of another, the only place you can do that is in a member function, so in this case that means the constructor.

If you're going to create a static array like that, you probably want to be using std::array instead of std::vector - the whole point of vector is that it can grow dynamically.

std::array<int, 250> m_arr;

This declares an array of integers which has a capacity of 250 and has a fixed size. It's faster than a vector but it is always 250 large. You would then have to track the "in-use" count of it and other management overhead yourself.

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

If you were worrying about memory allocation, you could tell the vector to allocate memory upfront like this:

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

There are a host of other issues with your code, but they aren't directly related to your question so I'm not going to address/highlight them.

But in terms of dealing with your directorSize issues, you should consider providing an accessor that queries the vector or expose a const reference to the vector (this somewhat breaks encapsulation tho since it allows external callers to write code based on assumptions about your internal structure).

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM