存储与任务关联的名称列表
Storing list of names associated with tasks
所以我做了这个任务系统,或者我正在尝试做它,这样如果有人做了七个以上的任务,下一个人必须做七个。
双打(Bodine,Finn,Tycho)是人。现在我不知道我是否正确使用了它,(如果它们需要是双精度)以及我如何在这行代码中使用它们:
if (taskNumbers == 7)
{
std::cout << "It's " + /*what to do here? */ + "time!";
我想要的是,如果任务数大于 7,而 Bodine 已经完成了 7 个任务,它会说"这是他的时间!
#include <iostream>
using namespace std;
double Bodine;
double Finn;
double Tycho;
bool tasksDone = true;
int taskNumbers = 0;
int main()
{
if (taskNumbers > 7)
{
std::cout << "It's " + /*what to do here? */ + "time!";
return 1;
}
}
这是我的第一个项目之一(im 13,所以是的...我只需要知道如何使用下一个变量!
好吧,你并没有真正跟踪轮到谁了。此外,double
不是适合这里工作的工具。我会做这样的事情:
std::vector<std::string> users = { "Bodine", "Finn", "Tycho" };
int currentUser = 0;
现在我们有一个名字列表以及一个计数器,上面写着轮到谁了。0
是第一人称,1
是第二人称,2
是第三人称。然后我们需要逻辑来推进该计数器:
void advanceUser() {
if (++currentUser >= users.size()) {
currentUser = 0;
}
}
这会增加currentUser
,当它大于人数时,它会循环回0
,所以人们正确地轮流。
接下来关于任务逻辑,我会建议这样的东西:
int tasksDone = 0;
void incrementTasksDone() {
if (++tasksDone >= 7) {
advanceUser();
std::cout << "It's " + users[currentUser] +"'s time!" << std::endl;
tasksDone = 0;
}
}
在这里,我们有一个计数器,可以跟踪任务量,当它命中时7
,它会将其设置回0
,并在调用advanceUser
设置该权限后宣布轮到下一个用户了。
然后,您可以根据需要调用incrementTasksDone
,例如我像这样测试它:
int main()
{
for (int i = 0; i < 100; i++) {
incrementTasksDone();
}
}
例如,这将完成100个任务,因此轮次将在此过程中更改14次,并且每次都会打印消息。
此外,若要运行此示例,请务必添加以下内容:
#include <vector>
#include <string>
#include <iostream>
您好,欢迎来到C++。许多人会说C++对于初学者来说是一种糟糕的语言选择。好吧,我很久以前就开始C++自己,直到今天我还在学习。我是 100% 自学成才的,我没有今天人们在互联网上可用的大量信息以及可用的现代格式方面的优势。当我刚开始学习C++时,互联网正处于蓬勃发展的阶段;但当时大多数网站几乎都是纯文本,即使是简单的图片或图形也需要一段时间才能加载到屏幕上,因为这是在Dial Up
时代。今天,刚起步的人拥有这个网站、其他类似网站甚至 youtube 视频的优势。但是,我仍然喜欢尽我所能提供帮助,因为它不仅可以帮助您,而且还可以帮助我改进我已经学到的东西。C++多年来一直在发展,所以我在这里要做的是向你演示一个小应用程序,我相信它模仿了你描述的你正在尝试做的事情的行为。其中一些技术有点先进,特别是对于初学者,但我认为新手尽早学习这些概念是一个很好的选择。
Storage Types & Lifetime
-C++
基本上有4种主要的存储类型:Automatic
,Dynamic
,Static
和Thread
。我主要关注前 3 个。
Automatic:
它具有声明它的作用域的生存期,一旦该作用域从其右大括号退出,它将自动销毁}
Dynamic:
由指针表示但用new
声明的内存,并且必须具有匹配的delete
,或分别new[]
和delete[]
数组。它们的寿命可以超过其声明的范围。它们将一直存在,直到调用其匹配的删除。如果没有发生匹配的删除,这会导致内存泄漏,无效指针,悬空指针和引用以及未定义的行为。使用raw-pointers
时需要特别注意;建议使用containers
或smart pointers
.Static:
这些通常位于global
命名空间和/或global filespace
中。如果在main.cpp
中声明了static
,它将具有应用程序的生存期和整个程序的范围。如果它们在其他cpp
文件中声明,它们将具有该文件的范围,除非它们在某个header
文件中声明,则它们将具有其他翻译单元包含该标头的范围。它们类似于Automatic
,因为它们将自动销毁,但它们的不同之处在于它们只初始化一次,保持它们的状态,并且您只能拥有它们的单个实例。- 有关不同类型的存储分类的演示,请参阅我之前对此问答的回答。
Classes and Inheritance:
- (我不会涉及Polymorphism
)。
Classes:
Classes
和Structs
是用户定义的数据类型。- 两者之间的区别在于默认访问
- 默认情况下:
Structs
有Public Members
Classes
有Private Members
Class
或Struct
的成员可以是任何内置类型、指向类型的指针、其他用户定义的数据类型以及方法或函数。Member Variables
可以是任何Storage
Type
:Automatic
、Dynamic
、Static
和Thread
,但是,成员函数通常是Automatic
的,但可以Static
。如果您有member variable
则必须在Class's
Declaration
之外initialized
它才能解决它symbols
。- 默认情况下,它们具有
Constructors
和Destructors
,但可以创建自己的自定义Constructor
或Destructor
。你通常会看到人们用他们的简称提到他们:分别为ctor
和dtor
。- 一个类可以从另一个类继承。
Inheritance:
- 你有
Base
或Super
Classes
,你有Derived
或Child
Classes
- 当从
Base
类Inheriting
时,如果Base
类的ctor
是Public
,这意味着你可以创建一个同时具有Base
和Derived
Classes
的对象。有时你想要这种设计,但有时你不需要。- 如果您不希望用户能够创建
Base
Class
的实例,但能够创建Derived Class
的实例,那么您需要做的就是确保1st它的ctor
是Protected
。如果您将其声明Private
,那么即使是您的Derived
Classes
也无法访问它,因此无法声明它们。*第二 您要确保您的Destructors
-dtors
Virtual
;否则,您将遇到销毁类的顺序问题。Base
Class
可以有Virtual
Member Functions
,这意味着所有Derived
Classes
都必须Implement
该Function
。Base
Class
可以具有Purely Virtual
的Member Functions
,这与上面类似,但也阻止任何人声明此Base
Class
的实例,因为这会产生Base
Class
Abstract
,这意味着它是一个接口的想法。- 示例
Virtual
Function
:virtual update();
- 示例
Purely Virtual
: '虚拟更新() = 0;有许多
Containers
- (我会使用std::container
,但我不会涉及任何Algorithms
)
- 种容器可以满足不同的需求; 这些容器有助于保持程序简单,易于管理和调试,用户友好并防止将来出现许多麻烦,而不是使用
basic C Arrays
。- 有几种不同的类型,它们都有自己的目的和属性,我不会详细介绍它们的所有细节,因为您可以在网上找到有关它们的大量信息,但我将它们标记为并分组到它们的相似属性:分组是
Sequence Containers
、Associative Containers
、Unordered Containers
,这些都属于std::
namespace
。分组之间的主要区别是:Sequence Containers
像arrays
和linked lists
,Associative Containers
binary trees
,Unordered Containers
与binary trees
相似,只是它们不按顺序排列,它们被认为是hash tables
。
Sequence:
vector
、dequeue
、queue
、list
、forward_list
、array
Associative:
set
、multiset
、map
、multimap
Unordered:
unordered_set
,unordered_multiset
,unordered_map
, unordered_multimap'- 这些容器之所以强大,是因为能够快速遍历它们,或者根据您使用的容器快速插入和查找。另一个很好的功能是帮助内存管理过程。最后是可以对它们进行工作的众多
algorithms
和iterators
。- 有关
stl
的更多信息,我建议通过以下方式观看此YouTube系列Bo Qian
Smart Pointers
有几种不同的类型,但最重要的两种是std::shared_ptr<T>
和std::unique_ptr<T>
.两者之间的主要区别在于,shared
对有多少对象可以访问它有一个reference count
;这意味着它有一个公共类型接口,可以使用复制语义; 另一方面,unique
一次只有1
owner
,它可以转让所有权,但一旦转让,原始所有者就无法再访问它。您不能复制unique
,但可以移动它们。这些智能指针有助于使用dynamic memory
和生命周期对象管理,以防止内存泄漏、无效指针、悬空指针和引用、未定义的行为等。它们分别有助于最大限度地减少new
delete
和new[]
&delete[]
的使用。
现在您已经了解了C++
程序中经常看到的一些概念;现在,我将向您展示我根据我认为您正在尝试做的事情编写的简单应用程序:
#include <array>
#include <exception>
#include <memory>
#include <string>
#include <iostream>
class Person {
protected:
std::string name_;
int tasksCompleted_;
public:
const std::string& whoIs() const { return name_; }
int numberTasksCompleted() const { return tasksCompleted_; }
virtual void performTask() = 0;
protected:
explicit Person(const std::string& name) : name_{ std::move(name) } {}
virtual ~Person() = default;
};
class Bodine final : public Person {
private:
static int currentTask;
public:
explicit Bodine(const std::string& name = std::string("Bodine")) : Person(name) {}
virtual ~Bodine() = default;
virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Bodine::currentTask = 0;
class Finn final : public Person {
private:
static int currentTask;
public:
explicit Finn(const std::string& name = std::string("Finn")) : Person(name) {}
virtual ~Finn() = default;
virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Finn::currentTask = 0;
class Tycho final : public Person {
private:
static int currentTask;
public:
explicit Tycho(const std::string& name = std::string("Tycho")) : Person(name) {}
virtual ~Tycho() = default;
virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Tycho::currentTask = 0;
int main() {
try {
std::array<std::shared_ptr<Person>, 3> people{
std::shared_ptr<Person>(new Bodine()),
std::shared_ptr<Person>(new Finn()),
std::shared_ptr<Person>(new Tycho())
};
// For each person in array
const int MAX_TASKS = 7;
int currentPerson = 0;
for (auto& p : people) {
std::cout << p->whoIs() << " has performed task #:n";
while (p->numberTasksCompleted() < 7) {
p->performTask();
std::cout << p->numberTasksCompleted() << 'n';
if (p->numberTasksCompleted() == MAX_TASKS) {
currentPerson++;
if (currentPerson <= (people.size() - 1) ) {
std::cout << "It's your turn " << people[currentPerson]->whoIs() << " to do some tasks.n";
}
break;
}
}
}
} catch( std::runtime_error& e ) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
-输出-
Bodine has performed task #:
1
2
3
4
5
6
7
Finn has performed task #:
1
2
3
4
5
6
7
Tycho has performed task #:
1
2
3
4
5
6
7
链接到上面的程序。
我知道这需要阅读很多内容;但是请仔细查看应用程序,尝试看看它在做什么。您可以将其直接复制并粘贴到您自己的 IDE 中,并尝试构建并运行它以查看它的实际效果。希望这会让您了解C++
是什么。
-编辑-
关于上面的代码:它比它真正需要的要复杂一些。首先,你不会真正看到一个人的身份,因为它是自己的阶级。我这样做只是为了证明inheritance
是什么。我选择使用std::array
而不是std::vector
主要是因为您的提案中3
了特定的人。如果在编译时人数未知,那么std::vector
将是要使用的正确容器。您也不需要使用继承。此外,如果您查看派生classes
3
会有很多duplicate
代码。我还使用shared_ptrs
来展示如何使用它们,但在您的特定情况下不是必需的。我还在Derived
Classes
中使用了static member variables
来展示static storage
。
这是上述代码的简化版本,用于模仿您的行为。两个程序执行相同的任务类似,唯一的主要区别是:使用inheritance
与purely virtual methods
、static member storage
、container type
,以及通过使用shared_ptr
dynamic memory
。
#include <exception>
#include <iostream>
#include <string>
#include <vector>
class Person {
private:
std::string name_;
int tasksCompleted_;
public:
explicit Person(const std::string& name) : name_(name), tasksCompleted_(0) {}
const std::string& whoIs() const { return name_; }
int numberTasksCompleted() const { return tasksCompleted_; }
void performTask() { tasksCompleted_++; }
};
int main() {
try {
std::vector<Person> people{
Person( "Bodine" ),
Person( "Finn" ),
Person( "Tycho" )
};
// For each person in array
const int MAX_TASKS = 7; // Don't like magic numbers!
int currentPerson = 0; // Needed variable
for (auto& p : people) {
std::cout << p.whoIs() << " has performed task #:n";
while (p.numberTasksCompleted() < MAX_TASKS) {
p.performTask();
std::cout << p.numberTasksCompleted() << 'n';
if (p.numberTasksCompleted() == MAX_TASKS) {
currentPerson++;
if (currentPerson <= (people.size() - 1) ) {
std::cout << "It's your turn " << people[currentPerson].whoIs() << " to do some tasks.n";
}
break;
}
}
}
} catch( std::runtime_error& e ) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
这是此版本程序的链接!
- Pybind11:将元组列表从Python传递到C++
- 从链接列表c++中删除一个项目
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- C++如何通过用户输入删除列表元素
- 读取文件的最后一行并输入到链接列表时出错
- 复制列表初始化的隐式转换的等级是多少
- LNK2038、MSVS2017 MAGMA的原因列表
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 没有为自己的结构调用列表推回方法
- 使用简单类型列表实现的指数编译时间.为什么
- 一对向量构造函数:初始值设定项列表与显式构造
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 存储与任务关联的名称列表
- 逆转具有值的双关联列表
- 在C 中逆转一个通用双关联列表
- 如何获取与某个扩展相关联的程序列表
- 将源与C++程序的程序集列表相关联
- 访问与命令行参数关联的整数列表
- 如何创建一个将模板对象与自己的模板列表关联起来的方法?
- 与枚举器列表成员相关联的整数值是多少?