在c++中使用命名空间和单独编译

问题描述 投票:0回答:1

我第一次尝试在我创建的新类上使用命名空间和单独的编译。但是,我遇到了一个错误,内容为“无法解析的外部符号”。我不确定我做错了什么。

这是头文件

#pragma once
////File name: COP3014KA.h
//Author: Khalid Abdallah
//assignment number: 4
//description: Using classes and derived classes to create objects within the classes. includes constructors to intilize.
//Last Changed: August 2, 2023
//header file for class COP3014

#ifndef COP3014_H
#define COP3014_H

#include <iostream>
#include <string>
using namespace std;

namespace Abdallah //new namespace for class
{
    // COP3014 class 
    class COP3014 {
    protected:
        string firstName, lastName, zNumber;
        int quiz1, quiz2, quiz3, midterm, finalExam;
        double totalGrade;
        char letterGrade;

    public:
        // Constructors
        COP3014();// default constructor initializes all values to 0

        COP3014(string fname, string lname, string znum); //intializes all values to the maximum

        void input(); //gets inputs from the user for each field


        // Setter functions
        void setFirstName(string fname);

        void setLastName(string lname);

        void setZNumber(string znum);

        void setQuiz1(int grade);

        void setQuiz2(int grade);

        void setQuiz3(int grade);

        void setMidterm(int grade);

        void setFinalExam(int grade);


        // Getter functions
        string getFirstName() const;

        string getLastName() const;

        string getZNumber() const;

        int getQuiz1() const;

        int getQuiz2() const;

        int getQuiz3() const;

        int getMidterm() const;

        int getFinalExam() const;

        double getTotalGrade() const;

        char getLetterGrade()  const;


        // Grade computation function
        void computeTotalGrade();

        // Letter grade computation function
        void computeLetterGrade();

        // Absent check function
        void checkAbsences();

        // Output function
        void printInfo() const;
    };

    
}
#endif

实施

//File name: KhalidAbdallah_Assignment3.cpp
//Author: Khalid Abdallah
//assignment number: 4
//description: Using classes and derived classes to create objects within the classes. includes constructors to intilize.
//Last Changed: August 2, 2023
//implementation file


#include <iostream>
#include <string>
#include "COP3014KA.h"
using namespace std;
using namespace Abdallah;
// COP3014 class 
class COP3014 {
protected:
    string firstName, lastName, zNumber;
    int quiz1, quiz2, quiz3, midterm, finalExam;
    double totalGrade;
    char letterGrade;

public:
    // Constructors
    COP3014()// default constructor
    {
        firstName = "student";
        lastName = "name";
        zNumber = "11111111";
        quiz1 = 0;
        quiz2 = 0;
        quiz3 = 0;
        midterm = 0;
        finalExam = 0;
    } 
    COP3014(string fname, string lname, string znum)
    {
        firstName = fname;
        lastName = lname;
        zNumber = znum;
        quiz1 = 20;
        quiz2 = 20; 
        quiz3 = 20;
        midterm = 100;
        finalExam = 100;
    }

    void input() //gets inputs from the user for each field
    {
        cout << "Enter first name: " << endl;
        cin >> firstName;   
        cout << "Enter last name: " << endl;
        cin >> lastName;
        cout << "Enter z number: " << endl;
        cin >> zNumber;
        do
        {
            cout << "Enter quiz 1 grade: " << endl;
            cin >> quiz1;
        } while (quiz1 < 0 || quiz1 > 20);
         
        do 
        {
                cout << "Enter quiz 2 grade: " << endl;
                cin >> quiz2;
        } while (quiz2 < 0 || quiz2 > 20);
           
        do
        {
                cout << "Enter quiz 3 grade: " << endl;
                cin >> quiz3;
        } while (quiz3 < 0 || quiz3 > 20);
        cout << "Enter midterm grade: " << endl;
        cin >> midterm;
        cout << "Enter final exam grade: " << endl;
        cin >> finalExam;
    }


    // Setter functions
    void setFirstName(string fname) 
    {
        firstName = fname; 
    }
    void setLastName(string lname) 
    {
        lastName = lname; 
    }
    void setZNumber(string znum)
    { 
        zNumber = znum; 
    }
    void setQuiz1(int grade)
    { 
        quiz1 = grade;
    }
    void setQuiz2(int grade) 
    {
        quiz2 = grade;
    }
    void setQuiz3(int grade) 
    {
        quiz3 = grade;
    }
    void setMidterm(int grade)
    { 
        midterm = grade; 
    }
    void setFinalExam(int grade)
    {
        finalExam = grade;
    }

    // Getter functions
    string getFirstName() const
    { 
        return firstName; 
    }
    string getLastName() const
    {
        return lastName; 
    }
    string getZNumber() const
    {
        return zNumber; 
    }
    int getQuiz1() const
    { 
        return quiz1;
    }
    int getQuiz2() const
    { 
        return quiz2;
    }
    int getQuiz3() const
    { 
        return quiz3;
    }
    int getMidterm() const
    { 
        return midterm;
    }
    int getFinalExam() const
    { 
        return finalExam;
    }
    double getTotalGrade() const
    { 
        return totalGrade;
    }
    char getLetterGrade()  const
    { 
        return letterGrade;
    }


    // Grade computation function
    void computeTotalGrade() {
        totalGrade = ((quiz1 + quiz2 + quiz3) / 3.0) + (midterm * 0.3) + (finalExam * 0.5);
    }

    // Letter grade computation function
    void computeLetterGrade() {
        if (totalGrade >= 90) {
            letterGrade = 'A';
        }
        else if (totalGrade >= 80 && totalGrade <= 90) {
            letterGrade = 'B';
        }
        else if (totalGrade >= 70 && totalGrade <= 80) {
            letterGrade = 'C';
        }
        else if (totalGrade >= 60 && totalGrade <= 70) {
            letterGrade = 'D';
        }
        else {
            letterGrade = 'F';
        }
    }

    // Absent check function
    void checkAbsences() {
        if (midterm <= 0 || finalExam <= 0)
            letterGrade = 'F';
    }

    // Output function
    void printInfo() const {
        cout << firstName << " " << lastName << " - " << zNumber << endl;
        cout << "Quiz 1: " << quiz1 << endl;
        cout << "Quiz 2: " << quiz2 << endl;
        cout << "Quiz 3: " << quiz3 << endl;
        cout << "Mid term: " << midterm << endl;
        cout << "Final: " << finalExam << endl;
        cout << "Total grade: " << totalGrade << endl;
        cout << "Final grade: " << letterGrade << endl;
    }
};

申请

//File name: COP3014KA_APP.cpp
//Author: Khalid Abdallah
//assignment number: 4
//description: Using classes and derived classes to create objects within the classes. includes constructors to intilize.
//Last Changed: August 2, 2023
//Application file for COP3014KA.cpp
//uses header and implementation files.

#include <iostream>
#include <string>
#include "COP3014KA.h"
using namespace std;
using namespace Abdallah;

int main()
{
    //sample test cases 
    COP3014 student1("Frank", "Fabulous", "Z12345678");
    student1.setQuiz1(20);
    student1.setQuiz2(20);
    student1.setQuiz3(10);
    // Set midterm and final exam grades
    student1.setMidterm(0);
    student1.setFinalExam(100);

    // Compute the total grade and letter grade
    student1.computeTotalGrade();
    student1.computeLetterGrade();
    student1.checkAbsences();
    // Print student information and grades
    student1.printInfo();

    cout << endl;

    COP3014 student2("Gina ", "Genius ", "Z98765432");
    student2.setQuiz1(20);
    student2.setQuiz2(20);
    student2.setQuiz3(20);
    // Set midterm and final exam grades
    student2.setMidterm(98);
    student2.setFinalExam(95);

    // Compute the total grade and letter grade
    student2.computeTotalGrade();
    student2.computeLetterGrade();
    student2.checkAbsences();
    // Print student information and grades
    student2.printInfo();

    cout << endl;

    COP3014 student3;
    student3.input();
    cout << endl;
    // Compute the total grade and letter grade
    student3.computeTotalGrade();
    student3.computeLetterGrade();
    student3.checkAbsences();
    // Print student information and grades
    student3.printInfo();

    cout << endl;
}

我尝试过链接这些文件,但我相信它们没有链接。它可能与定义的命名空间有关,因为文件之间没有传输任何内容。

c++ class namespaces header-files implementation
1个回答
0
投票

下面的评论应该可以回答您的大部分问题。

头文件应包含声明,但不包含定义。例如:

// This is a function declaration. There is no function body.
int f();

// 
This is a function definition. It has a function body.
int g() {
    return 42;
}

好的,这是头文件

MyClass.h
。它包含一个示例类声明和一个示例函数声明。因为声明出现在命名空间
tbx
内,所以它们是可见的。它们在命名空间之外、“文件级”范围内不可见。

请注意,函数

my_factory
返回类型为
MyClass
的对象。那应该很有趣。

#ifndef MYCLASS_H
#define MYCLASS_H

namespace tbx
{
    class MyClass
    {
    public:
        // these are all declarations, no definitions
        static int my_static_variable;
        int my_instance_variable;
        MyClass();
        void my_member_function();
    };

    MyClass my_factory();
}
#endif  // MYCLASS_H

// end file: MyClass.h

接下来,我们有文件

MyClass.cpp
。它包含标题中内容的定义。这要棘手得多,所以我写了很多评论来解释为什么某些名称必须限定作用域,而其他名称则不需要限定作用域。

#include "MyClass.h"

// We are at "file-level" scope.
// Static member variables must scoped:
// once to enter the namespace, and then again to enter the class.
int tbx::MyClass::my_static_variable = 42;

// The same goes for the constructor function.
// Scope once to enter namespace, and then again to enter class.
// From there, the name of the constructor function is visible.
tbx::MyClass::MyClass()
    : my_instance_variable( 7 )  // Now we are inside the class,
{}                               // so no scoping is needed.

// This is "file-level scope.
// Must scope to namespace to find class name.
// Must scope again to enter class and find function.
void    // This return type does not require scoping, ...
tbx::MyClass::my_member_function()  // but the function name does.
{
    // Now we are inside the scope of MyClass.
    // Names do not have to be scoped here.
    my_instance_variable = 8;
}

// This is still "file-level" scope.
// Must scope to namespace in order see function defined there.
// Must also scope to namespace in order to identify the return type.
tbx::MyClass        // The return type requires scoping.
tbx::my_factory()   // So does the function name.
{
    // No scoping is needed to refer to MyClass from inside the function.
    //
    // The `tbx::` which prefixes `my_factory` causes us 
    // to enter the namespace. After that, any name visible 
    // in the namespace is also visible inside the function.
    // That is why MyClass is visible here. 
    // 
    // Those closing brace at at the end of the function 
    // causes us to exit namespace.

    MyClass mc;  // no scoping needed here. 
    return mc;
}
// end file: MyClass.cpp

最后,文件

main.cpp
只是一个简单的测试驱动程序。

#include "MyClass.h"
int main()
{
    // Scoping required to see inside the namespace.
    tbx::MyClass mc;
    mc = tbx::my_factory();
    return 0;
}
// end file: main.cpp

对函数使用尾随返回类型的一大优点是,如果返回类型使用与函数本身在同一范围内可见的名称,则不必限定返回类型的范围。

将函数

my_factory
的定义与上面给出的定义进行比较。这个定义可以在文件
MyClass.cpp
中使用,而不是上面写的:

auto tbx::my_factory() -> MyClass  // at this point we are inside 
{                                  // the scope of the the namespace.
    return MyClass{};              // Therefore, MyClass does not need 
}                                  // any scoping

无论哪种方式都可以,但现在,大多数人都选择尾随返回类型。

© www.soinside.com 2019 - 2024. All rights reserved.