c++类的几种成员函数声明后必须要定义吗?

c++类的几种成员函数声明后必须要定义吗?

1. 构造函数和析构函数

test.h

#pragma once
class CTest
{
public:
	CTest();
	~CTest();
};

test.cpp

#include "stdafx.h"
#include "test.h"

情况一:

main.cpp

#include "stdafx.h"
#include "test.h"

int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}

编译通过

[外链图片转存失败(img-dT6rg82V-1562739765618)(C:\Users\panbaoru\AppData\Roaming\Typora\typora-user-images\1562730641546.png)]

在没有实例化该类对象时,即使没有对构造函数和析构函数定义,编译通过。
(emmm我觉得这好像有点废,因为都没有用,都没有编译test.h和test.cpp

情况二:

main.cpp

int _tmain(int argc, _TCHAR* argv[])
{
	CTest test;

	return 0;
}

编译失败

[外链图片转存失败(img-F5yOPJFv-1562739765619)(C:\Users\panbaoru\AppData\Roaming\Typora\typora-user-images\1562730774806.png)]

类实例化时一定会调用构造函数和析构函数,所以当构造函数和析构函数没有定义时,链接时报错:找不到该函数定义

2. 普通成员函数

test.h

#pragma once
class CTest
{
public:
	CTest();
	~CTest();
	void test();
};

test.cpp

#include "stdafx.h"
#include "test.h"
CTest::CTest()
{

}

CTest::~CTest()
{

}

情况一:

main.cpp

int _tmain(int argc, _TCHAR* argv[])
{
	CTest test;

	return 0;
}

编译成功

因为没有调用test的test成员函数,所以链接时不会去找该定义,因此链接通过。

情况二:

main.cpp

int _tmain(int argc, _TCHAR* argv[])
{
	CTest test;
	test.test();
	return 0;
}

编译失败

[外链图片转存失败(img-akCM1Lnv-1562739765619)(C:\Users\panbaoru\AppData\Roaming\Typora\typora-user-images\1562738809749.png)]

因为调用test的test成员函数,所以链接时会去找该定义,结果没找到,因此链接报错。

3. 虚函数

test.h

#pragma once
class CTest
{
public:
	CTest();
	~CTest();
	virtual void testVirtual();
};

test.cpp

#include "stdafx.h"
#include "test.h"
CTest::CTest()
{

}

CTest::~CTest()
{

}

main.cpp

int _tmain(int argc, _TCHAR* argv[])
{
	CTest test;
	return 0;
}

编译失败

[外链图片转存失败(img-X968vU7b-1562739765619)(C:\Users\panbaoru\AppData\Roaming\Typora\typora-user-images\1562739013865.png)]

 实例化类的虚函数必须有定义,原因如下:有虚函数作为成员函数的类, 它的实例化-对象, 在运行过程分配到的内存不止是它的成员数据, 还有一个指向该类虚函数表(vtable)的指针, 虚函数表中的每个数据项都是一个虚函数的入口地址; 如果一个对象的虚函数只有声明而没有实现, 就会出现这个虚函数表找不到本应作为其数据项之一的某函数的入口地址, 虚函数表在运行前不能装载完成, 所以产生连接错误!

定义该虚函数后链接成功!

4. 纯虚函数

test.h

#pragma once
class CTest
{
public:
	CTest();
	~CTest();
	virtual void testPureVirtual() = 0;
};

test.cpp

#include "stdafx.h"
#include "test.h"
CTest::CTest()
{

}

CTest::~CTest()
{

}

main.cpp

int _tmain(int argc, _TCHAR* argv[])
{
	CTest test;
	return 0;
}

编译报错

[外链图片转存失败(img-B92dv1Ue-1562739765620)(C:\Users\panbaoru\AppData\Roaming\Typora\typora-user-images\1562739654824.png)]

包含纯虚函数的类是抽象类,抽象类不可以实例化,否则报错。原因如下:
纯虚函数出现在接口类中,并赋值为0,不要为该函数分配函数地址,从而阻止类的实例化!纯虚函数是没有定义的,如果实现了也不是纯虚函数啦!

总结

  1. 需要实例化类的虚函数必须有定义,而仅仅定义带有虚函数的类且虚函数没有实现,该类编译是可以通过的!
  2. 纯虚函数出现在接口类中,并赋值为0,不要为该函数分配函数地址,从而阻止类的实例化!纯虚函数是没有定义的,如果实现了也不是纯虚函数啦!
  3. 一般的成员函数可以只有声明,前提是在应用中不能调用该函数,否则会因找不到定义产生连接错误!

函数地址,从而阻止类的实例化!纯虚函数是没有定义的,如果实现了也不是纯虚函数啦!


#### 总结

1. 需要实例化类的虚函数必须有定义,而仅仅定义带有虚函数的类且虚函数没有实现,该类编译是可以通过的!
2.  纯虚函数出现在接口类中,并赋值为0,不要为该函数分配函数地址,从而阻止类的实例化!纯虚函数是没有定义的,如果实现了也不是纯虚函数啦!
3.  一般的成员函数可以只有声明,前提是在应用中不能调用该函数,否则会因找不到定义产生连接错误!

上一篇:为什么屏幕亮度不使用lux,而是使用nit作为单位?


下一篇:横空出世的可视化新工具,帮你更轻松地探索数据