调程序时忘了为啥,写了一小段测试程序,再简单不过,结果跑出了Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
这个错误信息是在MSVC下的debug模式下跑出的,如果用release版本,则程序直接崩溃!!很严重的错误有木有!
老规矩,先奉上结论:父类没有虚函数(且没有虚析构函数),子类含有虚函数(只含有虚析构函数也算)时,如果指针类型为父类的(但指向子类的实例),就会出现Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)。
我猜测这是由于父类没有虚函数,也就没有为虚函数表分配空间。但是子类有虚函数,也就为虚函数表分配了空间!至于为神马这样就会出错,就不得而知了!
当然,好的编程习惯还是要将父类的析构函数设为虚函数的,这样一来子类的析构函数总是会被调用,这样比较不容易出现内存泄露。
程序如下:
#include <iostream>
class A {
public:
A() {
std::cout << __FUNCTION__ << std::endl;
}
~A() { //解决方案1:将这个函数改为virtual的,推荐~这样释放下面的pB指针时也会调用B的析构函数
std::cout << __FUNCTION__ << std::endl;
}
//virtual void fA(){} //解决方案2:给父类A添加个虚函数
};
class B : public A {
public:
B() {
std::cout << __FUNCTION__ << std::endl;
}
virtual ~B() {//添堵的虚函数1:父类A完全没有虚函数,子类的析构函数设为虚函数照样报错
std::cout << __FUNCTION__ << std::endl;
}
virtual void func() {} //添堵的虚函数2:父类A完全没有虚函数,子类的有虚函数就会报错
};
void main() {
A* pB = new B();
delete pB;
pB = nullptr;;
}
分享到:
相关推荐
p1->next = phead->next; phead->next = p1; p1 = p; } } // 另一种方法 void reserve_another_method(list_node* head) { list_node* p = head; list_node* q = head->next; while (q != NULL) { list_...
### C++:打飞碟_课程设计报告 #### 一、问题简介 本课程设计的目标是利用C++语言和Funcode平台开发一个简单的射击类游戏——打飞碟。游戏的基本玩法是玩家通过鼠标控制大炮发射炮弹来击中不断出现的飞碟,从而获得...
该项目是基于C++语言实现的一个电话簿管理系统,作为大学C++课程设计的一部分。电话簿管理系统的主要功能包括添加联系人信息、查询联系人、修改联系人信息以及删除联系人等。 ### 二、类的设计 #### 1. CTelRecord...
printf("%d %d %p %p\n", phead->num, phead->data, phead, phead->pNext); printall(phead->pNext); } } ``` `printall` 函数用于递归地打印链式栈中的所有节点的信息。 #### 4. 出栈函数 `pop` ```c ...
在给定的文件中,我们涉及到了一个C++编程实现的扑克牌游戏,主要涉及到三个类:`Card`、`Player`以及游戏相关的函数。以下是这些知识点的详细说明: 1. **`Card` 类**: - `Card` 类表示扑克牌,包含私有成员变量...
- `CStu_node* phead`: 链表的头指针。 - **成员函数**: - `addnode()`: 添加一个新的学生信息到链表中。该函数首先提示用户输入学生的基本信息及成绩,然后创建一个新节点并将其插入到链表中。 ### 三、程序运行...
4 <-> 6 <-> 8 <-> 10 <-> 12 <-> 14 <-> 16 - **代码解析** ```cpp struct BSTreeNode { int m_nValue; // value of node BSTreeNode* m_pLeft; // left child of node BSTreeNode* m_pRight; // right ...
pNew->pNext = pHead->pNext; pHead->pNext = pNew; } return pHead; } ``` #### 遍历链表 遍历链表是为了读取链表中的数据,可以通过指向头节点的指针开始,沿着`pNext`指针访问每个节点,直到遇到`NULL`...
Visual C++MFC入门教程 目录 +-- 第一章 VC入门 |------ 1.1 如何学好VC |------ 1.2 理解Windows消息机制 |------ 1.3 利用Visual C++/MFC开发Windows程序的优势 |------ 1.4 利用MFC进行开发的通用方法介绍 |----...
if ((pCurrent->m_nValue) > value) { addBSTreeNode(pCurrent->m_pLeft, value); } else if ((pCurrent->m_nValue) ) { addBSTreeNode(pCurrent->m_pRight, value); } else { //cout重复加入节点"; } } } // 遍历...
- 引入 `<iostream>`、`<string>`、`<iomanip>` 和 `<fstream>` 头文件以支持输入输出流、字符串操作、格式化输出及文件操作等需求。 2. **命名空间**: - 使用 `using namespace std;` 语句简化标准库的使用。 ...
PLT p = pHead->pNext; while (p != NULL) { printf("%d ", p->data); p = p->pNext; } printf("\n"); } bool Insert(PLT pHead, int val) { PLT p = pHead; while (p->pNext != NULL) { p = p->pNext; }...
p->next = phead->v; phead->v = p; } } // 查找指定顶点的邻接表 alist* ph(int p) { alist* phead = head; while (phead != NULL) if (phead->u == p) return phead; else phead = phead->next; } // ...
pHead->next = pNode->next; final: free(pNode); return TRUE; } ``` **解析:** - 检查`pHashTbl`和对应位置的链表是否为`NULL`。 - 使用`find_data_in_hash`查找要删除的节点。 - 如果找到该节点: - 如果...
4 <-> 6 <-> 8 <-> 10 <-> 12 <-> 14 <-> 16 ``` #### 解决方案 为了实现这一目标,我们需要利用到二叉查找树的一个性质:**中序遍历**能够得到升序排列的节点值序列。因此,我们的策略是通过递归进行中序遍历,...
然后,比较两个链表的头节点值,如果`pHead1`的值小于等于`pHead2`,则将`pHead1`的下一个节点与`pHead2`进行合并,并将结果作为`pHead1->next`,返回`pHead1`作为新链表的头节点。反之,将`pHead2`的下一个节点与`...
PrintfListNode(pHead->next, true); std::cout << pHead->data << "<-"; } else { // 从头到尾打印 // ... 代码 } } ``` ##### 5.2 非递归方法 非递归方法使用栈来保存所有节点,最后依次弹出并打印。 ```...
例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 2、代码详解 # -*- coding:utf-8 -*- class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def deleteDuplication(self, ...