我第一次尝试在我创建的新类上使用命名空间和单独的编译。但是,我遇到了一个错误,内容为“无法解析的外部符号”。我不确定我做错了什么。
这是头文件
#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;
}
我尝试过链接这些文件,但我相信它们没有链接。它可能与定义的命名空间有关,因为文件之间没有传输任何内容。
下面的评论应该可以回答您的大部分问题。
头文件应包含声明,但不包含定义。例如:
// 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
无论哪种方式都可以,但现在,大多数人都选择尾随返回类型。