Coding In C++, Day03

5、构造函数
构造函数没有返回类型(根本就是没有返回类型,返回类型绝对不要以为是void)。构造函数函数名称必须和类名称一样。当一个对象被创建是,构造函数会自动被执行,以完成对象的构造,构造函数参数来自构造实际参数。
构造函数定义语法:
class C_Name {

    ....
    
    类名 (形式参数表){
    ...
    }


};


6、构造函数可以通过构造参数实现重载。
7、如果一个类没有定义任何构造函数,那么编译器就会缺省地为其提供一个void参数构造函数,该构造函数对于基本类型的成员变量不做初始化,对于类类型的成员变量,是会调用其相应的类型的无参构造

8、对象的创建过程。
分配内存->调用构造函数->调用类类型成员的构造函数->构造函数代码

9、初始化表。写在构造函数名称和构造函数体之间的初始化列表。
class 类名称 {
    类名称(...) : 初始化表
    {
    构造函数体
    }
};

(1)如果类中有常量或者引用型的成员变量,必须通过初始化表对其初始化。(P.S.成员变量的定义是在构造函数构造对象的时候发生的。)

/*
 *如果类中有常量或者引用型的成员变量,必须通过初始化表对其初始化。(P.S.成员变量的定义是在构造函数构造对象的时候发生的。)
 * */
#include <iostream>
using namespace std;
int g_data = 1000;
class A {
public:
	A (void) : m_c (100), m_r (g_data) {
		//m_c = 100;//ERROR
		//m_r = g_data;//ERROR
	}
	void print (void) {
		cout << m_c << ' ' << m_r << endl;
	}
private:
	const int m_c;
	int& m_r;
};
int main (void) {
	A a;
	a.print ();
	return 0;
}


(2)成员变量的初始化顺序仅与其被声明的顺序有关,而于初始化表的顺序无关。成员变量之间应该尽可能减少相互依赖(p.s这叫做耦合),因为初始化顺序很可能影响相互依赖的成员。


(post script:注意严格区别"初始化语句"和"赋值语句"
 int a = 0;//初始化语句,"="为初始化操作符
 int b ;
 b = 0;//赋值语句,"="为赋值操作符
 )


10、类定义语法分为声明部分和实现部分。我们往往将类的声明和实现分开书写。
声明部分:class C_Name {/*这里面的都应该是声明语句。包括成员对象(简单对象,复杂对象),成员函数。*/};

五、this指针
(p.s.this指针不是类的成员变量。this是成员函数缺省的形式参数)
1、一般而言,在类的构造函数或者成员函数中,关键字this表示一个指针,对于构造函数而言,this指向正在被构造的对象,对于成员函数而言,this指向调用该函数的对象。
2、this指针的用途
(1)在类的内部,可以用this对成员变量加以区分。
 (2) 在成员函数中返回调用对象自身。
 (3) 在成员函数内部通过参数向外界传递调用对象自身,以实现对象间交互。

老 -问题-> 学

师 <-答案- 生

/*
 * this指针举例
 *
 *老 -问题-> 学
<p> *师 <-答案- 生</p> * 
 */
#include <iostream>
using namespace std;
class Student;
class Teacher {
public:
	void educate (Student* s);
	void reply (const string& answer) {
		m_answer = answer;
	}
private:
	string m_answer;
};
class Student {
public:
	void ask (const string& question, Teacher* t) {
		cout << "问题:" << question << endl;
		t->reply ("不知道。");
	}
};
void Teacher::educate (Student* s) {
	s->ask ("什么是this指针?", this);
	cout << "答案:" << m_answer << endl;
}
int main (void) {
	Teacher t;
	Student s;
	t.educate (&s);
	return 0;
}


C++不允许如下交叉类:
class A {
  B m_b;
};
class B {
  A m_a;
};
sizeof (A) ?
class C {
  C m_c;
};
但是可以有这样的交叉:
class B;
class A{
    B & m_b;//或者B * m_b;
};
class B{
    A & m_a;//或者A * m_a;
};
class C{
    C *m_c;//或者C& m_c;
};

六、常函数与常对象
1.如果在一个类的成员函数的参数表后面加上const关键字,那么这个成员函数就被称为常函数,常函数的this指针是一个常指针。在常函数内部无法修改成员变量,除非该变量具有mutable属性。而且在常函数内部也无法调用非常函数。
2.常对象:拥有const属性的对象,对象引用或指针。
常对象只能调用常函数。
同型的常函数和非常函数可以构成重载关系(因为他们的形式参数确实不一样,一个是常指针this,    一个是普通指针this)。常对象调用常版本,非常对象调用非常版本。如果没有非常版本,非常对象也可以调用常版本。
/*
 *常函数与常对象
 * */
#include <iostream>
using namespace std;
class A {
public:
//	void bar (void) {
//		cout << "非常bar" << endl;
//	}
	void bar (void) const {
		cout << "常bar" << endl;
	}
//  void XXXbarYYY (A* this) {}
	void foo (void) const {
//		m_i = 100;
		const_cast<A*>(this)->m_i = 100;
	}
	void print (void) const {//const关键字是用来修饰缺省形式参数this的,也就是说本函数的this指针是常指针。
		cout << m_i << endl;
	}
//	_ZNK1A3fooEv (const A* this) {
//		const_cast<A*>(this)->m_i = 100;
//	}
	int m_i;//mutable int m_i;//加上mutable修饰符后,常函数就可以修改成员变量m_i了。
};
void func (void) /*const*/ {}
int main (void) {
	A a;
	a.foo ();
	a.print ();
	const A& r = a;
	r.bar ();
//	XXXbarYYY (&r); // const A*
	a.bar ();
//	XXXbarYYY (&a); // A*
	return 0;
}



理解下面三个const修饰符修饰的是谁?

const XXX 函数名 (const YYY yyy) const {//第一个const修饰返回类型
                        //中间的const修饰形式参数类型
      ...                //最后一个const修饰成员函数的缺省形式参数this.
}

七、析构函数
class 类名 {
  ~类名 (void) {//析构函数参数必须是void型,函数名称必须是~类名称
     析构函数体;
  }
};
当一个对象被销毁时自动执行析构函数。
局部对象离开作用域时被销毁,堆对象被delete时被销毁。
如果一个类没有定义任何析构函数,那么系统会提供一个缺省析构函数。缺省析构函数对基本类型的成员变量什么也不干,对类类型的成员变量,调用相应类型的析构函数。
一般情况下,在析构函数中释放各种动态分配的资源。
构造:基类->成员->子类
析构:子类->成员->基类

C和C++的安全编码是指在编写C和C++代码时,采取一系列的措施来确保代码的安全性和防止常见的安全漏洞。由于C和C++是底层的编程语言,它们允许对内存直接进行操作,这也使得它们容易受到各种安全威胁的攻击。 在进行安全编码时,有几个关键的原则需要遵循。首先是验证输入。由于输入数据往往是来自外部,我们需要对输入进行验证,以确保它们符合预期的格式和范围。这样可以防止缓冲区溢出和格式化字符串漏洞等攻击。 其次,应该正确地管理内存。C和C++允许直接控制内存的分配和释放,但这也意味着需要手动管理内存的生命周期。如果没有正确地分配和释放内存,会导致内存泄漏和非法内存访问等问题。因此,务必要仔细检查并指定正确的内存操作。 此外,还应注意避免使用不安全的函数和功能。一些函数和功能可能存在安全风险,如strcpy和scanf等。应该使用更安全的替代函数,如strncpy和fgets等,以提高代码的安全性。 最后,代码的安全性也需要经过不断的测试和审查。通过进行静态代码分析和动态测试,可以发现和纠正代码中的潜在安全问题。此外,代码审查也是非常重要的,通过互相审查可以找到潜在的漏洞和错误。 总而言之,C和C++的安全编码需要遵循验证输入、正确管理内存、避免使用不安全函数和功能以及进行测试和审查等原则。只有通过采取适当的安全措施,才能确保代码的安全性并防止潜在的安全漏洞。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值