简体   繁体   中英

When I split up my C++ class into a header and implementation I get 20 compiler errors which don't make sense

I was splitting up my program into a header and implementation file per usual, however, when I tried to run the code, I got a ton of compile errors. This seems to be an issue with my computer or IDE, but I have not seen it before. This should be relatively simple as it is for a class project. The code is as follows:

colorPicker.h

#pragma once
class colorPicker {
private: 
    string colorArray[7];
public: 
    colorPicker(); 
    void printAllColors(); 
    string randomColor(); 
};

colorPicker.cpp

#include "colorPicker.h"
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <stdio.h>
#include <stdlib.h>
using namespace std; 



colorPicker::colorPicker() {
    colorArray[0] = "Red"; 
    colorArray[1] = "Green";
    colorArray[2] = "Purple";
    colorArray[3] = "Yellow";
    colorArray[4] = "Orange";
    colorArray[5] = "Indigo";
    colorArray[6] = "Pink";
}

void colorPicker::printAllColors() {
    for (int i = 0; i < 7; i++) {
        cout << colorArray[i] << endl;
    }
}

string colorPicker::randomColor() {
    srand((unsigned)time(0)); 
    int j = 0; 
    j = rand() % 7; 
    return colorArray[j];
}

main.cpp

#include "colorPicker.h"
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <stdio.h>
#include <stdlib.h>
using namespace std;


int main() {
    colorPicker p;
    p.printAllColors(); 
    cout << "Random Color: " << p.randomColor() << endl; 
    system("pause");
    return 0; 
 }

There are 20 errors given by the compiler, however, they all seem to be stemming from two undeclared identifiers which are most definitely declared. I am at a loss for what I could possibly do to fix it, and this project is due Sunday. Thank you.

Here are the errors Tons of Errors

You need #include "colorPicker.h" in colorPicker.cpp . Each .cpp file is handled basically independently by the compiler and they are all joined at the end by the "linker." When the compiler looks at colorPicker.cpp without an include of the corresponding header, it's at a loss as to the definition of all the classes you're working with.

There are a few things you are doing wrong. I'll just pick on a couple.

Firstly, each header file you write should be self-contained - in the sense that, if it relies on content of some other headers, it includes that header. If a compilation unit (a formal name for a source file with a .cpp in your case) includes your header, it should not have to include something else your header depends on.

Second, it is a bad idea for a header to rely on any using directive, such as using namespace std . There are plenty of explanations of that available, so I won't repeat.

To understand the above, look at colorPicker.h

 class colorPicker { private: string colorArray[7]; public: colorPicker(); void printAllColors(); string randomColor(); }; 

Firstly, this depends on string , but there is no definition of string visible in the header file. Usage of that type depends on the standard header <string> .

Second, that string type is within namespace std . So your header relies on the compilation unit (the source file that includes your header) having previously used a using directive ie using namespace std .

To fix these two problems, change the header to

 #ifndef SOME_MACRO_UNIQUE_TO_YOUR_COLOR_PICKER_HEADER
 #define SOME_MACRO_UNIQUE_TO_YOUR_COLOR_PICKER_HEADER

 #include <string>

 class colorPicker
 {
     private: 
         std::string colorArray[7];
     public: 
       colorPicker(); 
       void printAllColors(); 
       std::string randomColor(); 
 };

 #endif

(I've also done some minor changes of layout, since I have various reasons to prefer that.

However, the #include <string> means that this version will not fail to compile, as yours does, if it is included by a compilation unit that does not have #include <string> .

The usage of the fully qualified name std::string , rather than string , also means there is no dependence on the using directive using namespace std . It also means compilation errors can't be triggered in your header if your compilation unit has another using directive.

I've also used an include guard, rather than #pragma once . Although most modern compilers support #pragma once , it is actually not standard C++ (a #pragma , by definition in the standard, is a compiler-specific hook). Include guards are supported in standard C++.

If you've done that, your code should mostly compile as is. However, optionally, you may wish to

  • remove the using directives using namespace std from your other files. If you do that, you will need to change the definition of colorPicker::randomColor() in colorPicker.cpp so it returns the fully qualified type std::string rather than string .
  • Remove #include <string> from files that have #include "colorPicker.h" . This is possible, since colorPicker.h now includes <string> . This step is optional, since there is no problem with including standard headers more than once in a compilation unit.

A few other notes

  • In C++, although it is not a major concern, it is usually considered better to use include <cstdio> and <cstdlib> rather than the C headers <stdio.h> and <stdlib.h> .
  • Your code is calling srand((unsigned)time(0)) whenever colorPicker::randomColor() is called. It is better to only call it once in an entire program, not in a function that may be called multiple times.

You may need add head file and in colorPicker.h. And the std namespace is needed while using string.

BTW, the header guards is recommended strongly.

#ifndef COLOR_PICKER_H
#define COLOR_PICKER_H

#pragma once

#include <string>

class colorPicker {
private:
    std::string colorArray[7];
public:
    colorPicker();
    void printAllColors();
    std::string randomColor();
};

#endif

A header file should be self-contained as far as #include s go. That means that you should be able to #include the header file without having to include other stuff before it!

Your colorPicker.h does not meet that requirement. It apparently uses std::string from the standard library but does not have an #include <string> on top, so everyone who uses colorPicker.h has to remember to put an #include <string> before it. That's pretty annoying.

Even worse, colorPicker.h refers to std::string as string , which implies a using std::string; or using namespace std; somewhere before any #include "colorPicker.h" line, and both of those are very bad coding style in C++, if not used in tighter scopes.

Here's how to fix the header file:

#pragma once
#include <string>

class colorPicker {
private: 
    std::string colorArray[7];
public: 
    colorPicker(); 
    void printAllColors(); 
    std::string randomColor(); 
};

As far as your *.cpp files go, I can see that you are using #include "stdafx.h" . Why? It's a non-standard Microsoft thing completely unnecessary in your case. You are also using it incorrectly. It must be the first include. Just remove it entirely.

Some other suggested cleanup:

  • using namespace std; lines in *.cpp files is not as bad as in header files, but if I were you, I'd just get rid of it completely. Just use complete names. Say std::cout , not cout . And so on. It's just the most consistent way and it avoids a lot of trouble.
  • You include a lot of headers which you don't need. For example, what's <ctime> for?
  • Don't use system("pause"); . Do not look for artificial ways of pausing a command-line program.

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