以下实现了一个基于 std::vector 派生的 SiteReplies 类,结合内存分配(alloc())、对象管理、生命周期控制、序列化/反序列化、异常处理等功能,覆盖实际开发中常见的场景。
1. 完整代码实现
cpp
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <ctime>
// 前置声明
class ResponseMessage;
class SiteReplies;
// 回复消息类:表示站点的一条回复
class ResponseMessage {
private:
std::string id; // 回复唯一ID
std::string content; // 回复内容
std::string author; // 回复作者
time_t createTime; // 创建时间
bool isPublished; // 是否发布
public:
// 构造函数
ResponseMessage(const std::string& id_, const std::string& content_,
const std::string& author_, bool published = false)
: id(id_), content(content_), author(author_), isPublished(published) {
createTime = time(nullptr); // 默认当前时间
}
// 析构函数
~ResponseMessage() {
std::cout << "[销毁] 回复ID: " << id << std::endl;
}
// 拷贝构造(禁用,避免浅拷贝)
ResponseMessage(const ResponseMessage&) = delete;
ResponseMessage& operator=(const ResponseMessage&) = delete;
// 移动构造
ResponseMessage(ResponseMessage&& other) noexcept {
id = std::move(other.id);
content = std::move(other.content);
author = std::move(other.author);
createTime = other.createTime;
isPublished = other.isPublished;
other.createTime = 0;
}
// 成员方法
void publish() { isPublished = true; }
void editContent(const std::string& newContent) { content = newContent; }
// 获取器
std::string getId() const { return id; }
std::string getContent() const { return content; }
std::string getAuthor() const { return author; }
time_t getCreateTime() const { return createTime; }
bool getIsPublished() const { return isPublished; }
// 序列化:将对象转为字符串(用于存储/传输)
std::string serialize() const {
std::ostringstream oss;
oss << id << "|" << content << "|" << author << "|"
<< createTime << "|" << (isPublished ? "1" : "0");
return oss.str();
}
// 反序列化:从字符串重建对象
static ResponseMessage* deserialize(const std::string& data) {
std::istringstream iss(data);
std::string id, content, author, createTimeStr, publishedStr;
if (!std::getline(iss, id, '|') || !std::getline(iss, content, '|') ||
!std::getline(iss, author, '|') || !std::getline(iss, createTimeStr, '|') ||
!std::getline(iss, publishedStr, '|')) {
throw std::invalid_argument("反序列化失败:数据格式错误");
}
time_t createTime = std::stoll(createTimeStr);
bool isPublished = (publishedStr == "1");
return new ResponseMessage(id, content, author, isPublished);
}
};
// 站点回复容器:继承std::vector<ResponseMessage*>,扩展业务逻辑
class SiteReplies : public std::vector<ResponseMessage*> {
private:
std::string siteId; // 所属站点ID
size_t maxCapacity; // 最大容量
public:
// 构造函数
SiteReplies(const std::string& siteId_, size_t maxCap = 1000)
: siteId(siteId_), maxCapacity(maxCap) {}
// 析构函数:释放所有回复对象
~SiteReplies() {
clearReplies();
std::cout << "[销毁] 站点" << siteId << "的回复容器" << std::endl;
}
// 禁用拷贝(避免浅拷贝导致重复释放)
SiteReplies(const SiteReplies&) = delete;
SiteReplies& operator=(const SiteReplies&) = delete;
// 移动构造
SiteReplies(SiteReplies&& other) noexcept
: std::vector<ResponseMessage*>(std::move(other)),
siteId(std::move(other.siteId)),
maxCapacity(other.maxCapacity) {
other.maxCapacity = 0;
}
// 核心方法:分配新回复(内存分配+容器添加)
ResponseMessage* alloc(const std::string& replyId,
const std::string& content,
const std::string& author) {
// 容量检查
if (size() >= maxCapacity) {
throw std::overflow_error("回复容器已达最大容量:" + std::to_string(maxCapacity));
}
// 检查ID唯一性
if (findReplyById(replyId) != nullptr) {
throw std::invalid_argument("回复ID已存在:" + replyId);
}
// 分配内存并添加到容器
ResponseMessage* newReply = new ResponseMessage(replyId, content, author);
push_back(newReply);
std::cout << "[分配] 新增回复ID:" << replyId << " 站点:" << siteId << std::endl;
return newReply;
}
// 根据ID查找回复
ResponseMessage* findReplyById(const std::string& replyId) const {
auto it = std::find_if(begin(), end(), [&](const ResponseMessage* msg) {
return msg->getId() == replyId;
});
return (it != end()) ? *it : nullptr;
}
// 发布指定ID的回复
bool publishReply(const std::string& replyId) {
ResponseMessage* reply = findReplyById(replyId);
if (reply) {
reply->publish();
std::cout << "[发布] 回复ID:" << replyId << std::endl;
return true;
}
return false;
}
// 批量发布作者的所有回复
size_t publishRepliesByAuthor(const std::string& author) {
size_t count = 0;
for (auto* reply : *this) {
if (reply->getAuthor() == author && !reply->getIsPublished()) {
reply->publish();
count++;
}
}
std::cout << "[批量发布] 作者" << author << "的" << count << "条回复" << std::endl;
return count;
}
// 清空所有回复(释放内存)
void clearReplies() {
for (auto* reply : *this) {
delete reply; // 释放单个回复
}
clear(); // 清空vector
std::cout << "[清空] 站点" << siteId << "的所有回复" << std::endl;
}
// 导出回复到文件
bool exportToFile(const std::string& filename) const {
std::ofstream file(filename);
if (!file.is_open()) {
return false;
}
file << "站点ID:" << siteId << "\n";
file << "回复总数:" << size() << "\n";
for (const auto* reply : *this) {
file << reply->serialize() << "\n";
}
file.close();
std::cout << "[导出] 站点" << siteId << "的" << size() << "条回复到" << filename << std::endl;
return true;
}
// 从文件导入回复
size_t importFromFile(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
throw std::runtime_error("无法打开文件:" + filename);
}
std::string line;
// 跳过站点ID行
std::getline(file, line);
// 跳过回复总数行
std::getline(file, line);
size_t imported = 0;
while (std::getline(file, line) && !line.empty()) {
try {
ResponseMessage* reply = ResponseMessage::deserialize(line);
// 检查容量和ID唯一性
if (size() >= maxCapacity) break;
if (findReplyById(reply->getId()) == nullptr) {
push_back(reply);
imported++;
} else {
delete reply; // 重复ID,释放内存
}
} catch (const std::exception& e) {
std::cerr << "[导入失败] " << e.what() << std::endl;
}
}
file.close();
std::cout << "[导入] 站点" << siteId << "成功导入" << imported << "条回复" << std::endl;
return imported;
}
// 获取站点ID
std::string getSiteId() const { return siteId; }
// 获取容量信息
size_t getMaxCapacity() const { return maxCapacity; }
size_t getUsedCapacity() const { return size(); }
};
// 辅助函数:打印回复详情
void printReplyInfo(const ResponseMessage* reply) {
if (!reply) {
std::cout << "回复不存在" << std::endl;
return;
}
std::cout << "------------------------" << std::endl;
std::cout << "回复ID: " << reply->getId() << std::endl;
std::cout << "内容: " << reply->getContent() << std::endl;
std::cout << "作者: " << reply->getAuthor() << std::endl;
// 第一步:将返回值赋值给局部变量(左值)
time_t createTime = reply->getCreateTime();
// 第二步:对左值取地址传入ctime
std::cout << "创建时间: " << ctime(&createTime);
std::cout << "发布状态: " << (reply->getIsPublished() ? "已发布" : "未发布") << std::endl;
std::cout << "------------------------" << std::endl;
}
// 主函数:演示完整使用流程
int main() {
try {
// 1. 创建站点回复容器(站点ID: blog_001,最大容量5)
SiteReplies siteReplies("blog_001", 5);
std::cout << "=== 初始化站点" << siteReplies.getSiteId() << "的回复容器 ===" << std::endl;
std::cout << "最大容量: " << siteReplies.getMaxCapacity() << std::endl;
// 2. 分配新回复
ResponseMessage* r1 = siteReplies.alloc("r001", "这是第一条回复", "user_001");
ResponseMessage* r2 = siteReplies.alloc("r002", "C++真好用", "user_002");
ResponseMessage* r3 = siteReplies.alloc("r003", "继承vector要注意内存管理", "user_001");
// 3. 打印回复详情
std::cout << "\n=== 打印r002详情 ===" << std::endl;
printReplyInfo(r2);
// 4. 编辑回复内容
r2->editContent("C++容器扩展真灵活");
std::cout << "\n=== 编辑后r002详情 ===" << std::endl;
printReplyInfo(r2);
// 5. 发布回复
std::cout << "\n=== 发布回复 ===" << std::endl;
siteReplies.publishReply("r001");
siteReplies.publishRepliesByAuthor("user_001");
// 6. 查找回复
std::cout << "\n=== 查找回复r003 ===" << std::endl;
printReplyInfo(siteReplies.findReplyById("r003"));
// 7. 导出回复到文件
std::cout << "\n=== 导出回复 ===" << std::endl;
if (!siteReplies.exportToFile("replies_blog_001.txt")) {
std::cerr << "导出文件失败" << std::endl;
}
// 8. 测试容量限制(故意触发异常)
std::cout << "\n=== 测试容量限制 ===" << std::endl;
siteReplies.alloc("r004", "第四条回复", "user_003");
siteReplies.alloc("r005", "第五条回复", "user_004");
try {
siteReplies.alloc("r006", "第六条回复", "user_005"); // 超出容量
} catch (const std::overflow_error& e) {
std::cerr << "捕获异常: " << e.what() << std::endl;
}
// 9. 导入回复(演示)
std::cout << "\n=== 导入回复 ===" << std::endl;
SiteReplies newSite("blog_002");
newSite.importFromFile("replies_blog_001.txt");
// 10. 清空回复
std::cout << "\n=== 清空回复 ===" << std::endl;
siteReplies.clearReplies();
} catch (const std::exception& e) {
std::cerr << "程序异常: " << e.what() << std::endl;
return 1;
}
std::cout << "\n=== 程序正常结束 ===" << std::endl;
return 0;
}
2. 核心功能说明
| 功能模块 | 实现要点 |
|---|---|
| 内存管理 | alloc() 方法负责分配 ResponseMessage 对象并加入容器,析构函数/clearReplies() 释放所有对象,避免内存泄漏 |
| 容器扩展 | 继承 std::vector<ResponseMessage*> 并扩展业务方法(查找、发布、导入导出等) |
| 数据校验 | 分配回复时检查容量限制、ID唯一性,避免非法数据 |
| 序列化/反序列化 | 支持回复对象与字符串的互转,实现持久化(文件导入导出) |
| 异常处理 | 捕获容量溢出、ID重复、文件操作失败等异常,保证程序健壮性 |
| 生命周期控制 | 禁用拷贝构造,使用移动构造避免浅拷贝问题,明确对象所有权 |
3. 编译与运行
- 编译命令(g++):
g++ -std=c++17 site_replies.cpp -o site_replies - 运行:
./site_replies - 运行后会生成
replies_blog_001.txt文件,包含回复的序列化数据