简体   繁体   English

从C#切换到C ++。 我的代码出了什么问题? 我需要标题我正在尝试做什么? 一个文件问题中的类定义

[英]Switching from C# to C++. What's wrong with my code? do I NEED headers for what I'm trying to do? Class definitions within one file issue

I've been programming in C# for a few years now, as it was my first language. 我已经用C#编程了几年,因为这是我的第一语言。 I'm trying to brush up on my c++ because I will be working on something soon that is coded in that. 我正在努力提高我的c ++,因为我将很快开发一些编码的东西。

What is wrong with this code: (I know there might be a lot of things wrong. C++ is so different than C# in what it needs). 这段代码出了什么问题:(我知道可能存在很多错误.C ++与C#的不同之处在于它所需要的)。 Someone told me that I don't know how to declare classes correctly in C++, and that I need to define my classes using headers. 有人告诉我,我不知道如何在C ++中正确声明类,并且我需要使用头来定义我的类。 Do I NEED headers? 我需要标题吗? This is a small program just to test and would like to know if this can be accomplished without it. 这是一个小程序,只是为了测试,想知道是否可以在没有它的情况下完成。 And are the missing headers the only issue here? 丢失的标题是唯一的问题吗? I had a error about not being able to access Parse in Company, but when I add public in front of Company class name, it throws more errors. 我有一个关于无法在公司中访问Parse的错误,但是当我在公司类名称前添加public时,会引发更多错误。

AUGH! AUGH! So frustrating. 太令人沮丧了。

#include "std_lib_facilities.h"
using namespace std;

class Employee
{
public:
    string screen_name;
    string real_name;
    string current_job;
    int employee_number;
    Employee(int no, string name1, string name2, string current_jobin)
    {
        screen_name=name1;
        real_name=name2;
        employee_number=no;
    current_job=current_jobin;
    }
};

class Project
{
public:
    Vector<Employee> Employees;
    int max_worker_quota;
    int project_id;
    string project_name;
    Project(int no_in,int max_in,string title_in)
    {
        max_worker_quota=max_in;
        project_name=title_in;
        project_id=no_in;
    }
};

unsigned int split(const std::string &txt, vector<std::string> &strs, char ch)
{
    unsigned int pos = txt.find( ch );
    unsigned int initialPos = 0;
    strs.clear();

    // Decompose statement
    while( pos != std::string::npos ) {
        strs.push_back( txt.substr( initialPos, pos - initialPos + 1 ) );
        initialPos = pos + 1;

        pos = txt.find( ch, initialPos );
    }

    // Add the last one
    strs.push_back( txt.substr( initialPos, std::min( pos, txt.size() ) - initialPos + 1));

    return strs.size();
}

class Company
{
Vector<Employee> Employeelist;
Vector<Project> Projectlist;

    void Parse(string input)
    {
        //Case Statements
        vector<string> temp;
        split( input, temp, ' ' );

        if (temp[0]=="S")
        {
            //Add Employee to Company
            Employee myEmployee=Employee(atoi(temp[1].c_str()),temp[2],temp[3],temp[4]);
            Employeelist.push_back(myEmployee);
        }
        else if (temp[0]=="C")
        {
            //Add Project to Company
            Project myProject=Project(atoi(temp[1].c_str()),atoi(temp[2].c_str()),temp[3]);
            Projectlist.push_back(myProject);
        }
        else if (temp[0]=="L")
        {
            //Add Employee to Project list
            //Not Implemented-Find Project by temp[1] which is a int
        }
        else if (temp[0]=="A")
        {
        }
        else if (temp[0]=="D")
        {
        }
        else if (temp[0]=="PS")
        {
        }
        else if (temp[0]=="PC")
        {
        }
    }
};

int main(int argc, char *argv[])
{
string input;
cout<<"Command:: ";
cin>>input;
Company myCompany;
myCompany.Parse(input); //Input is in the format X Name Name etc etc. Arguments separated by spaces

return 0;
}

First of all, you don't need headers for test purposes. 首先,您不需要标题用于测试目的。 But you can not make a real program without them, because the headers define the interface of separately compiled program parts. 但是如果没有它们,你就无法创建一个真正的程序,因为标题定义了单独编译的程序部分的接口。 That's the way the C/C++ work, no way around. 这就是C / C ++的工作方式,没有办法解决。

Second, you have to add public: to your Company class and deal with the following errors. 其次,您必须将public:添加到您的Company类并处理以下错误。 It is just like the C# stuff: you have to make a function defined public void Parse(string) to be able to access it from outside the class. 它就像C#的东西:你必须使一个函数定义为public void Parse(string)才能从类外部访问它。 The C++ way is C ++方式是

class Foo { 
public:
void Bar();
}; 

Third, it is unconventional in C++ to define non-trivial functions inside class definition (the only exception being template classes). 第三,在C ++中定义类定义中的非平凡函数是非常规的(唯一的例外是模板类)。 That's the other side of the headers story tho. 那是标题故事的另一面。

OK, here is a brief explanation of basic header-related stuff. 好的,这里是基本标题相关内容的简要说明。

Program is usually divided into the set of separately compiled files, that is to say translation units. 程序通常分为单独编译的文件集,即翻译单元。 Each unit usually consist of one .cpp file and one or more header files ( .h ). 每个单元通常由一个.cpp文件和一个或多个头文件( .h )组成。 When these files are compiled you are getting a single binary .obj file. 编译这些文件时,您将获得一个二进制.obj文件。 This file contains objects - the code for your functions and stuff needed to initialize global (and namespace) objects. 该文件包含对象 - 函数代码和初始化全局(和命名空间)对象所需的东西。 To make a program you need to pass one or more object files to linker. 要创建程序,您需要将一个或多个目标文件传递给链接器。 In VS it happens behind the scene. 在VS中它发生在幕后。 You just add a .cpp file to your project tree and IDE will configure the project dependencies accordingly. 您只需将.cpp文件添加到项目树中,IDE将相应地配置项目依赖项。

This is how your code may look like: 这就是你的代码的样子:

//File: employee.h

#ifndef EMPLOYEE_HDR  /* include guard */
#define EMPLOYEE_HDR

#include <string>

using std::string;

class Employee {
public:
Employee (int no, string name1, string name2, string current_jobin);

void PayBonus(int amount);

void Fire(string reason);

int GetSalary() const
{ return m_Salary; }

/*...*/
protected:
int m_Salary;
string m_FirstName;
/* ... */
};

#endif

//File: employee.cpp
#include "employee.h"

Employee::Employee (int no, string name1, string name2, string current_jobin)
{
 //definition
}

void Employee::PayBonus(int amount)
{
 //definition
}

void Employee::Fire(string reason)
{
//definition
}

/* define other non-trivial class functions here */

//File: company.h

#ifndef COMPANY_HDR  /* include guard */
#define COMPANY_HDR

#include <vector>
using std::vector;

#include "employee.h"

class Company {
public:
Company();
void Hire(string name);

void WorldCreditCrunch() //life is unfair
{ FireEveryone(); }

void Xmas(); //pays $5 bonus to everyone

/* ... */

protected:

vector<Employee> m_Staff;

void FireEveryone();

/* ... */
};

#endif

//File: company.cpp

#include "company.h"

Company::Company()
{
 //definition
}

void Company::Hire(string name)
{
     //calculate new employee ID etc
     m_Staff.push_back(Employe( /*...*/));
}

void Company::FireEveryone()
{
    for(size_t i = 0; i < m_Staff.size(); ++i)
         m_Staff[i].Fire();

}

void Company::Xmas()
{
    for(size_t i = 0; i < m_Staff.size(); ++i)
         m_Staff[i].PayBonus(5);
}

/* ... */

//File: main.cpp

#include "company.h"

int main()
{
     Company c;

     c.Hire("John Smith");

     /* ...*/

     return 0;
}

So, basically we gonna have employee , company and main units. 所以,基本上我们会有员工公司主要单位。 The definition of Employee class in employee.h contains non-trivial functions declaration. employee.h中Employee类的定义包含非平凡函数声明。 A simple function like GetSalary() is defined right inside the class. GetSalary()这样的简单函数就在类中定义。 It gives a hint to the compiler to inline it. 它给出了编译器内联它的提示。 The employee.cpp contains the rest of function definitions; employee.cpp包含其余的函数定义;

The company.h file has #include "employee.h" preprocessor statement. company.h文件有#include "employee.h"预处理器语句。 So we may use Employee objects in the class definition and in its implementation file ( company.cpp ). 因此,我们可以在类定义及其实现文件( company.cpp )中使用Employee对象。

The main.cpp contains the program entry point. main.cpp包含程序入口点。 It is able to use Company class cause it includes "company.h". 它可以使用Company类,因为它包含“company.h”。

If we change something in the Employee::Hire() function implementation, only employee.obj will be recompiled. 如果我们在Employee :: Hire()函数实现中更改了某些内容,则只会重新编译employee.obj This is the main purpose of such program organization. 这是此类计划组织的主要目的。 But if we change the Employee interface (class definition in employee.h ) every program unit will require recompilation. 但是,如果我们更改Employee接口( employee.h类定义),则每个程序单元都需要重新编译。

Include guards are needed in case you do something like this: 如果您执行以下操作,则需要包含防护:

#include "employee.h"
#include "company.h"  /* will contain the 2nd inclusion of employee.h which will be 
                        prevented by include guard */

Projects based on Microsoft Visual C++ often use #pragma once for the same purpose. 基于Microsoft Visual C ++的项目通常使用#pragma once用于相同目的。 It is easier to use but generally not portable. 它更容易使用,但通常不便携。

If you put, for example, Employee::Hire definition in the employee.h the compiler will put the function code in both employee.obj and company.obj (cause the company.h includes employee.h ). 例如,如果在employee.h中放置Employee :: Hire定义,编译器会将函数代码放在employee.obj和company.obj中(因为company.h包含employee.h )。 When you try to link in such situation the linker will encounter 2 versions of the same function code and will give an error. 当您尝试在这种情况下链接时,链接器将遇到相同功能代码的2个版本,并将给出错误。 Inline functions are not compiled in into separate entities and thus don't cause such error. 内联函数不会编译到单独的实体中,因此不会导致此类错误。 Same goes about template code which is generated only when the template is instantiated. 模板代码也是如此,它仅在模板实例化时生成。 So, several translation units may have code for the same non-inline template functions. 因此,几个翻译单元可能具有相同的非内联模板功能的代码。

It is up to programmer to define the parts boundaries of the program. 程序员可以定义程序的部件边界。 You may put Company and Employee into single translation unit, if you want. 如果需要,您可以将公司和员工放入单个翻译单元。 The VS wizards tend to make a .h/ .cpp pair for each major class tho. VS向导倾向于为每个主要类别制作一个.h / .cpp对。 Try to make an MFC project and see for yourself. 尝试制作一个MFC项目并亲自看看。

These are the basics. 这些是基础知识。 As I mentioned in the comment above, you can get a full picture of such stuff from Stroustrup's "The C++ programming language" 正如我在上面的评论中所提到的,你可以从Stroustrup的“The C ++编程语言”中全面了解这些内容。

You use public to begin a section of public methods within the class, not on the class itself. 您使用public来开始类中的一部分公共方法,而不是类本身。 That is, you should add public: before the Parse method within the Company class. 也就是说,您应该在Company类中的Parse方法之前添加public: .

class Company
{
  Vector<Employee> Employeelist;
  Vector<Project> Projectlist;

public:
  void Parse(string input)
  {

This is just to expand on Pavel's third point since you requested in your comment. 这只是为了扩展帕维尔自你评论中提出要求以来的第三点。

What he means is basically this: in any real C++ project you'll want to separate out the definition of your class from its implementation into two files, a header file ( *.h ) and implementation file( *.cpp ). 他的意思基本上是这样的:在任何真正的C ++项目中,你都希望将类的定义从它的实现中分离出来,分成两个文件:头文件( *.h )和实现文件( *.cpp )。 Using your above example, it could be separated out like this: 使用上面的示例,它可以像这样分开:

// Employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include <string>

class Employee
{
public:
    Employee(int no, 
             std::string name1, 
             std::string name2, 
             std::string current_jobin);

private:
    std::string screen_name;
    std::string real_name;
    std::string current_job;
    int employee_number;    
};
#endif

// Employee.cpp
#include "Employee.h"

Employee::Employee(int no, 
                   std::string name1, 
                   std::string name2, 
                   std::string current_jobin)
{
    screen_name = name1;
    real_name = name2;
    employee_number = no;
    current_job = current_jobin;
}

// Company.h
#ifndef COMPANY_H
#define COMPANY_H
#include <vector>
#include <string>
#include "Employee.h"
#include "Project.h"

class Company
{
public:
    void Parse(std::string input);

private:
    std::vector<Employee> Employeelist;
    std::vector<Project>  Projectlist;
};
#endif

// Company.cpp
#include "Company.h"

void Company::Parse(std::string input)
{
    // your code for Parse in Company goes here
}

and your main.cpp would use the above like this: 你的main.cpp将使用上面这样的:

// main.cpp
#include <iostream>
#include <string>
#include "Company.h"

int main(int argc, char *argv[])
{
    std::string input;
    std::cout << "Command:: ";
    std::cin >> input;
    Company myCompany;
    //Input is in the format X Name Name etc etc. Arguments separated by spaces    
    myCompany.Parse(input); 
}

Now coming from a C# background you're probably wondering why things are done this way -- after all you end up with twice as many files! 现在来自C#背景你可能想知道为什么事情就这样完成 - 毕竟你最终得到了两倍的文件! The short answer is because C did it this way and C++ inherited a lot of baggage from C. 简短的回答是因为C这样做了,C ++从C继承了很多包袱。

The longer answer is because C++ doesn't use a 'module' system like what you'd find in C# and Java. 更长的答案是因为C ++不使用像C#和Java那样的“模块”系统。 When building a source file the compiler doesn't look anywhere else except for the current file it's compiling. 构建源文件时,编译器除了要编译的当前文件外,不会查看其他任何位置。 So the only way the compiler will know about the existence of a class, function or variable that you're using is if it shows up somewhere in the source file being compiled prior to use. 因此,编译器知道您正在使用的类,函数或变量是否存在的唯一方法是,如果它在使用前编译的源文件中出现。 The inclusion of all the headers pulled in by the #include directive together with the body of the source .cpp is what's termed as a 'compilation unit' -- it's a self-contained unit containing everything the compiler needs to know to successfully compile without looking else where. 包含#include指令引入的所有头文件和源.cpp的主体是所谓的“编译单元” - 它是一个独立的单元,包含编译器成功编译所需要知道的所有内容寻找别的地方。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java中的Java比使用C ++中的std :: vector快8倍。我做错了什么? - Java 8 times faster with arrays than std::vector in C++. What did I do wrong? 从Qt切换到Visual C ++之前,我需要了解什么? - What do I need to know before switching from Qt to Visual C++? 我需要做什么从C#应用程序引用c ++ dll? - What do I need to do reference a c++ dll from a C# application? C ++。 为什么我不能编译此代码? 使用const_cast删除constness有什么问题? - C++. Why I can't compile this code? What is wrong with removing constness using const_cast? C ++:尝试在模板化类中声明和定义模板化类。 我的代码有什么问题? - C++: Trying to declare and define templated class within templated class. What is wrong with my code? 用C ++归零2d数组。 我需要2个循环吗? - Zero a 2d array in C++. Do I need 2 for loops? 使用C ++进行VS2015的第一步。 托管/非托管类错误。 我做错了什么? - First steps with VS2015, using C++. Managed/Unmanaged Classes error. What I'm doing wrong? 我需要做什么来构建Android(NDK)的WebRTC(的一部分)? 它找不到C ++标头 - What do I need to do to build (parts of) WebRTC for Android (NDK)? It can't find C++ headers 用Java加密字符串,然后用C ++解密。 我还需要做些什么? - Encrypting a string in Java and decrypting it in C++. What i have to do more? `()` `{}` 在成员初始化列表中是什么意思? 我的代码有什么问题,output 不是我所期望的? - What do `()` `{}` mean in a member initializer list? What's wrong with my code that the output is not what I expect?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM