C++ | 手把手带你从C语言到C++-程序员宅基地

技术标签: C++  c++  开发语言  

目录

前言 

一、C++关键字 

二、命名空间

1、命名空间的引入 

2、命名空间的概念

3、命名空间的定义

4、命名空间的性质 

(1) 可以不连续性

(2)可嵌套性 

5、命名空间的使用 

(1)using声明

(2)using指示 

三、C++的输入与输出

 1、cout

 2、cin 

四、缺省参数 (默认实参)

 1、缺省参数的概念 

 2、缺省参数的分类

(1) 全缺省参数

 (2)半缺省参数

五、函数重载 

 1、函数重载的概念 

 2、函数重载的分类

(1)函数参数个数不同构成重载 

(2)函数参数类类型不同构成重载 

(3)函数参数顺序不同构成重载 

 3、函数重载的深刻理解

六、引用 

1、引用的基本概念

2、引用的特性

(1)定义引用时必须初始化 

(2)一个变量可以有多个引用

(3)引用一旦引用一个实体,再不能引用其他实体

3、常引用

4、引用的使用场景 

(1)作形参 

(2)作返回值

5、引用与指针的对比 

七、内联函数 

1、内联函数的概念 

2、内联函数的特性

八、auto关键字 

1、auto简介

2、auto使用过程中需要注意的细节

(1)auto必须要初始化; 

(2)auto和auto*以及auto&

(3)同一行定义多个变量必须未同类型

九、范围for语句

十、指针空值nullptr 


前言 

        在正式学习C++之前,我们首先得认识了解我们学习的C++创始人,Bjarne Stroustrup(本贾尼·斯特劳斯特卢普),本贾尼博士在使用C语言的过程中发现了C语言有许多方面上使用的不便,于是在C语言的基础上创立了C++,也就是说,C++文件中可以编译C语言代码,而C语言文件中也可以编译C++代码,可以理解为C++继承了许多C语言的特点。

一、C++关键字 

        与C语言相比,C++新增了一些关键字,从C语言的32个关键字到C++的63个关键字,我们之前也了解过关键字的概念,此处就不详细讲解,大概列出关键字,以供参考,具体每个关键字在后面的学习中慢慢了解;

 二、命名空间

1、命名空间的引入 

        我们的C++祖师爷本贾尼博士在使用C语言的过程中,发现了我们在定义变量名或者函数名的时候经常会与库函数重名,比如如下代码;

#include <stdio.h>
int main()
{
	int rand = 10;
	printf("%d\n", rand);
	return 0;
}

        在编写C语言代码时,我们定义一个名叫rand的变量,但是库函数中也有一个叫rand的函数名,因此,在编译以上代码时,会发生编译错误。在项目工程的开发中,经常是以多人分工完成同一个项目,最后将所有人的项目代码总和,实现项目工程,而在总和过程中,经常会发生同名的情况,因此我们的祖师爷本贾尼在设计C++的时候,提出了命名空间这一该概念。

2、命名空间的概念

        为了防止多个库将名字都放在全局命名空间(全局作用域)内引起的命名空间污染,命名空间提供了可控的机制,将全局命名空间进行了分割,其中每个命名空间都是一个作用域。

 3、命名空间的定义

        命名空间的定义有关键字+命名空间名+{}组成,具体定义如下; 

namespace zhangsan
{
	//声明或定义(命名空间成员)
	int a;
    char c;
    void Swap(int* p1, int* p2);
}

        以上代码定义了一个名叫zhangsan的命名空间,该命令空间有三个成员,分别声明了一个整型a,一个字符型c和一个函数Swap;

注意:命名空间不可定义在函数和类的内部 

4、命名空间的性质 

(1) 可以不连续性

        所谓可以不连续性也就是命名空间不必定义在同一块空间,我可以在这个文件定义zhangsan这个名字的命名空间,也可以在别的文件定义zhangsan这个名字的命名空间,编译器最后会将这些同名的命名空间合并成一个命名空间。

(2)可嵌套性 

        命名空间是可嵌套的,也就是我们平时说的套娃 ,具体如下代码;

namespace stu
{
	namespace zhangsan
	{
		int a;
	}
	namespace lisi
	{
		int a;
	}
}

 以上代码在全局作用域内定义了一个叫stu的命名空间,该命名空间里定义了两个子命名空间,分别为zhangsan和lisi,这两个命名空间分别有自己的成员;

5、命名空间的使用 

(1)using声明

using声明语句一次只引入命名空间的一个成员 

格式: using 命名空间名 :: 引入成员名

//std为标准库的命名空间名
//cout为其中的一个成员名
using std::cout;

        以上代码意思可理解为将命名空间名为std中的成员cout引入全局命名空间(全局作用域)中来。

 注:其中::(双冒号)为域操作符;

//引入标准库
#include <iostream>
//using声明
using std::cout;
using std::endl;
int main()
{
	cout << "hello world" << endl;
	return 0;
}

        以上代码段首先引入了iostream标准库,暂时可将其理解为C语言中引入stdio库一样的作用,std为标准库中变量存在的命名空间的名字,我们接着通过using声明将命名空间名为std中的cout(输出对象)和endl(换行符)引入到全局命名空间(全局作用域)中,所以接下来我们在局部作用域main函数中使用了cout和endl。

注:cout暂时可理解为输出的一种手段,类似C语言中的printf; 

(2)using指示 

 using指示语句一次可引入一个命名空间的所有成员

格式:using namespace 命名空间名


using namespace std;

         以上代码将命名空间名为std的所有成员都引入到了全局作用域(全局命名空间)中;

        阅读以下代码,让你对命名空间有更深刻的认识;

#include <iostream>

namespace A
{
	int i = 0;
	int j = 1;
	int k = 2;
}
int j = 15;

int main()
{
	//将命名空间A中所有成员引入全局作用域(全局命名空间)中
	using namespace A;
	i++; //对命名空间i++
	j++; // 错误  因为这里无法确定是对刚引入全局作用域中j++,还是对原本全局作用域中的j++
	A::j++; // 正确  对命名空间A的那个j++
	::j++;  // 正确  对原本全局作用域中的j++
	int k = 0;
	k++; // 对上一行的k++
	A::k++; // 对命名空间A中的k++
	return 0;
}
        在以上变量中,尤其是 j 变量更能让你深刻体会到 j 变量是确确实实的被引入全局作用域(全局命名空间)中,当 j 变量被引入全局作用域中,因为原本全局作用域有一个 j 变量, 因此在我们使用 j 变量时应该指出我们使用的是那个 j 变量,确保程序的严谨性;

 注:其实在我们平常写代码的过程中还有第三种引入方法,如下

#includ <iostream>

int main()
{
    //在我们使用的变量或函数名前加域作用符,并指定其来自的命名空间
    std::cout << "hello C++" << std::endl;
}

        以上代码使用的cout和endl是来自于std命名空间,我们可以在其语句的每个变量、对象或函数名前指定其命名空间来使用它;

 三、C++的输入与输出

        一提到C++的输入与输出,我们就不得不提cout和cin了,本文讲解此处的目的主要是浅浅的教大家学会用这两个对象,没错这两个并不是函数,而是两个对象,此处不做深入讲解,此文主要带着大家入门C++。

 1、cout

        该对象用于输出打印,功能类似于C语言中的printf,使用前需引入头文件 iostream,用法如下;

#include <iostream>

using std::cout;
using std::endl;

int main()
{
	int a = 20;
	cout << a << endl;
    return 0;
}

        既然要使用iostream里的成员,就必须将其引入作用域内,iostream的命名空间为std,因此使用前我们通过using声明引入了cout对象和endl(换行符),接着我们用流插入将a变量插入到cout对象中就可打印出结果;

注:

  1. cout是一个全局对象,并不是函数,使用前需包含头文件iostream,以及声明其所在命名空间std;
  2. <<是流插入运算符,目前无需对其了解;
  3. cout会自动识别对象类型,因此无需提供类型参数;

2、cin 

        cin为C++的输入对象,功能类似于C语言中的scanf函数,使用前也许引用头文件iostream,其命名空间名为std,其具体用法如下; 

#include <iostream>
using std::cin;
int main()
{
	int a = 0;
	cin >> a;
    return 0;
}

        通过以上代码,我们可以通过输入,对a进行赋值,cin的特点于cout类似,其中特别强调的是>>为流提取运算符;

 

        通过调试我们确实发现a的值被我们修改为了188; 

四、缺省参数 (默认实参)

1、缺省参数的概念 

         相比于C,缺省参数是C++特有的一种参数,该参数可以在函数调用函数时不传实参,而有一个默认的实参

#include <iostream>
using namespace std;
int func(int a = 1)
{
	return a;
}
int main()
{
	cout << func() << endl;    // 输出1
	cout << func(10) << endl;  // 输出10
	return 0;
}

        在上面代码中,当我们不给func函数传参时,a的默认值便为1,传参时,传过去的实参将会代替缺省参数,此时a便为10;

 2、缺省参数的分类

(1) 全缺省参数

void func1(int a = 1, int b = 2, int c = 3)
{
	cout << "a" << a << endl;
	cout << "b" << b << endl;
	cout << "c" << c << endl;
}

 (2)半缺省参数

void func2(int a, int b = 2, int c = 3)
{
	cout << "a" << a << endl;
	cout << "b" << b << endl;
	cout << "c" << c << endl;
}

注: 

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给;
  2. 缺省参数不能在函数声明和定义中同时出现,定义和声明都有时,缺省参数建议给在声明部分,而不给在定义部分;
  3.  缺省值必须是常量或者全局变量

五、函数重载 

1、函数重载的概念 

        函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

 以下我们用函数重载实现不同类型的相加函数;

int Add(int a, int b)
{
	return a + b;
}
double Add(double a, double b)
{
	return a + b;
}

int main()
{
	Add(1, 3); // 调用第一个Add函数
	Add(2.6, 5.7);  // 调用第二个Add函数
	return 0;
}

在调用Add函数时,编译器会通过形参找到对应的函数重载;

 2、函数重载的分类

(1)函数参数个数不同构成重载 

int Add(int a, int b)
{
	return a + b;
}
int Add(int a, int b, int c)
{
	return a + b + c;
}

         函数参数个数不同可以构成重载;

(2)函数参数类类型不同构成重载 

int Add(int a, int b)
{
	return a + b;
}
double Add(double a, double b)
{
	return a + b;
}

        函数参数类型不同也可以构成重载;

(3)函数参数顺序不同构成重载 

void func(int a, double b)
{

}
void func(double a, int b)
{

}

         函数参数顺序不同构成重载;

注意:相同类型参数顺序不同不能构成重载,比如两个int型,先后顺序不同不能构成重载

问题:函数返回值不同是否能构成重载呢? 

假设可以构成重载,有以下两个函数; 

int func(int a, double b)
{

}
void func(double a, int b)
{

}
int main()
{
	func();
	return 0;
}

        那么以上代码调用func函数时,会调用哪个函数呢?显而易见,这样的程序是有歧义的,调用函数时,编译器会通过参数来区分同名函数,而参数相同时,编译器也无法区分应该调用哪个函数了,因此返回值不同是不能构成函数重载的;

 3、函数重载的深刻理解

问:编译器是如何通过函数参数的不同来区分调用不同的函数呢?

        实际上,在函数编译的过程中,编译器会对每个函数进行修饰,不同的编译器修饰规则也不同,接下来我会带着大家在linux的环境下,用gcc(C语言编译)和g++(C++编译)带着大家来观察函数重载的过程;

以下为gcc(C语言方式)编译后形成的汇编代码;

        很显然,我们发现,用C语言方式编译后的汇编指令中的函数名并没有发生改变,函数名依然为原函数名;

 接下来,我们用g++(C++方式)编译上述代码,以下为生成的汇编代码结果;

        在以上汇编指令中,我们发现用C++编译放是进行编译生成的汇编指令中,函数的名字发生了变化,比如func1(int a, double b)中,func1变成了_Z5func1id,其中_Z为linux修饰函数特有前缀,5为函数名字符数,i为第一个参数类型int,d为第二个参数类型double,func2函数名依此类推

问:函数重载是否会影响程序的运行速度呢? 

        实际上,函数名的修饰是在编译过程中形成的,而只有在运行中的操作才会影响程序的运行速度,因此函数名的重载对运行速度并没有什么影响;

六、引用 

1、引用的基本概念

        引用不是新定义了一个变量,而是为一个已存在的变量取了别名,编译器不会为引用重新开辟一块空间,而是和引用对象共同管理一块空间;

int main()
{
	int a = 0;
	int& ra = a;  //定义一个引用类型变量
	return 0;
}

        以上代码定义了一个引用类型变量ra,当改变a的值时,ra的值也相应发生改变,因为他们共用一块内存空间;

 2、引用的特性

(1)定义引用时必须初始化 

int main()
{
	int a = 0;
	int& ra1;    // err  未初始化
	int& ra2 = a; // 正确
	return 0;
}

 (2)一个变量可以有多个引用

int main()
{
	int a = 0;
	int& ra1 = a;
	int& ra2 = a;
	int& ra3 = a;
	return 0;
}

        ra1、ra2、ra3都是a变量的引用,也就是a的别名;

(3)引用一旦引用一个实体,再不能引用其他实体

int main()
{
	int a = 0;
	int b = 2;
	int& ra1 = a;
	ra1 = b;    //此时仅仅只是将b变量的值赋值给引用变量ra1,而不会让ra1称为b的引用变量
	return 0;
}

 3、常引用

所谓常引用指的是在普通引用对象前加上const修饰; 

int main()
{
	const int a = 10;
	int& ra1 = a;  //err 权限放大,有只读到可写可读
	const int& ra2 = a;  // 正确

	int b = 20;
	int& rb1 = b;    // 正确
	const int& ra2 = b;  // 正确  权限缩小,由可读可写到只读
	return 0;
}

        第四行代码是错误的,因为原本的a变量是一个const修饰的变量,其只具有只读功能,而当赋值给他的引用ra1后,除了读以外还赋予ra写的功能,这本身并不合理,因此我们只能用一个常引用的变量来接收这个a变量;

 总结:权限可以缩小和平移,不可以放大

4、引用的使用场景 

(1)作形参 

void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

 (2)作返回值

int& count()
{
	static int count = 0;
	count++;
	return count;
}

 注意:选择引用作返回值时一定要当心,比如以下代码;

int& Add(int a, int b)
{
	int c = a + b;
	return c;
}

        此时明显是有问题的,当c变量以引用的方式返回时,出了作用域以后c变量被销毁,而返回的是c变量的引用,用的是同一块空间,可是这块空间在出作用域的时候被销毁了,这么做明显是不合理的;

5、引用与指针的对比 

引用与指针的不同点: 

  1. 引用只是定义了一个变量的别名,而指针是储存一个变量的地址;
  2. 引用在定义时必须要初始化,而指针没有要求
  3. 引用在初始化时引用一个实体后,不可再引用别的实体,而指针可以随时改变其指向;
  4. 没有NULL引用,而有NULL指针
  5.  sizeof中的含义不同,引用中sizeof结果为引用类型的大小,而指针的大小始终是固定的,再32位机器是4字节,在64位机器上是8字节
  6. 引用自加及是引用实体加1,而指针是往后偏移类型大小
  7. 有多级指针,没有多级引用
  8. 访问实体不同,指针需要解引用,而引用有编译器处理
  9. 引用比指针用起来更安全

七、内联函数 

1、内联函数的概念 

        在C语言的学习中,我们学习过一种由宏定义的函数,但是宏定义的函数由种种缺陷,因此C++语言的设计中,定义了一种类似于宏函数的函数,取名为内联函数;内联函数是以关键字inline开头,如以下代码;

inline void Swap(int& a, int b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
int main()
{
	int a = 10;
	int b = 20;

	Swap(a, b);
	return 0;
}

        接下来,我带着大家一起观察内联函数确实是取消调用了函数,而是在原处展开;首先我们要知道的是函数的调用在汇编语言中一般会有call语句,我的编译器(vs2022)默认在debug模式下不会对内联函数进行展开,因此需要进行如下设置;

 完成了上述两步步骤后就可在debug模式下,观察内联函数的展开;

        首先我们按F10进入调试模式(有些电脑需要按fn+f10),然后右键鼠标选择反汇编,我们在反汇编模式下进行调试。

        在汇编代码中,我们发现了call指令,其为函数调用函数,说明了函数开辟了栈帧空间调用函数,接着我们加上关键字再进行如上调试。

        在我们加入inline关键字后,我们并未在汇编指令中发现call指令,因此我们可以推断出在加入inline关键字后,函数并未采取开辟栈帧空间的方式进行调用,而是在原处展开。

 2、内联函数的特性

        1、inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。(其中的空间指的是程序空间

        2、inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。 

        3.、inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

八、auto关键字 

 1、auto简介

        C++使用auto修饰变量能自动识别变量类型,也就是说定义auto的变量接收赋值后,编译器会自动识别定义变量类型;

int main()
{
	auto a = 10;
	auto b = 'a';
	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	return 0;
}

        typeid是打印变量类型的函数,通过打印结果,我们确实发现auto能通过赋值的数据来自定义类型。

2、auto使用过程中需要注意的细节

(1)auto必须要初始化; 

int main()
{
    int a= 10;
    //auto x;  //err   错误写法,未初始化
    //x = a;
    auto y = a;   //正确
    return 0;
}

        其实仔细想想也知道,如果不初始化,编译器又怎么知道auto应该是什么类型呢,要开多大空间呢?

 (2)auto和auto*以及auto&

int main()
{
	int a = 10;
	auto p1 = &a;  //auto 与 auto* 是等价的写法,他们都表示一级指针
	auto* p2 = &a;
	cout << typeid(p1).name() << endl;
	cout << typeid(p2).name() << endl;
	auto ra1 = a;  // auto 与 auto& 也是如此,他们都表示a的别名
	auto& ra2 = a;	
	cout << typeid(ra1).name() << endl;
	cout << typeid(ra2).name() << endl;
	return 0;
}

        许多初学者会误以为auto*是二级指针,其实并不是的,是否加*两者没有什么本质上的区别;

(3)同一行定义多个变量必须未同类型

int main()
{
	auto a = 4, b = 8;
	auto a = 2, b = 4.9; // err  auto只会对第一个变量进行类型推测
	return 0;
}

        在同一行中,auto只会对其第一个变量进行类型推测,默认认为后面的变量与第一个变量同类型,因此,在同一行auto语句中,只能存在一种类型;

注:除上面三点以外,还有以下两点要特别注意; 

auto不能作为函数的形参,编译器无法对形参进行类型推导 ;

void test(auto a)  // err
{
    
}

 auto不能用于直接申请数组;


auto arr[] = { 1, 2, 4 };  // err

 九、范围for语句

        在C++11中,为我们提供了一种更简单的for语句,我们可以将这种新的for语句理解成为传统for语句的语法糖,具体用法如下;

for ( 变量 : 数组等) { 循环体 }

int main()
{
	int arr[] = { 1,2,3,4,5,6 };
	for (int e : arr)
	{
		cout << e << endl;
	}
	return 0;
}

        以上for语句会自动将数组的每个元素依次赋值给变量e,实际上我们可以int e写成 auto e,这样写可以增加代码的通用性;但我们发现如果我们想将数组的每个元素乘以2并打印出来单纯的拿e*2并不能做到,因此又有以下写法;

int main()
{
	int arr[] = { 1,2,3,4,5,6 };
	for (auto& e : arr)
	{
        e *= 2;
		cout << e << endl;
	}
	return 0;
}

         使用引用就使得每个e变量都是数组每个元素的别名,共同维护同一块空间,因此可以进行*2操作;

十、指针空值nullptr 

在C++发展中,推出了一种新的空指针------nullptr,相当于NULL,实际上,这是C++填补C语言的坑,在传统的C头文件中,是这么对NULL进行定义的; 

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

       也就是说C++文件中,NULL会被定义为整型0,而非((void*)0),可能有人认为这并没有上面大碍,因为有时0确实就是我们所说的NULL,但是在某些情况下会出现很大的BUG,如下代码;

void f(int)
{
    cout<<"f(int)"<<endl;
}
void f(void*)
{
    cout<<"f(void*)"<<endl;
}
int main()
{
    f(0);
    f(NULL);
    f((void*)NULL);
    return 0;
}

       在以上代码中,形成了函数重载,而在我们调用函数时,我们发现,我们传入整型时,调用的第一个函数,而我们传入NULL时,也是调用的第一个函数,这明显不符合我们的预期的,因此C++推出了nullptr,并将nullptr定义成((void*)0);

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Nice_W/article/details/128864472

智能推荐

软件测试流程包括哪些内容?测试方法有哪些?_测试过程管理中包含哪些过程-程序员宅基地

文章浏览阅读2.9k次,点赞8次,收藏14次。测试主要做什么?这完全都体现在测试流程中,同时测试流程是面试问题中出现频率最高的,这不仅是因为测试流程很重要,而是在面试过程中这短短的半小时到一个小时的时间,通过测试流程就可以判断出应聘者是否合适,故在测试流程中包含了测试工作的核心内容,例如需求分析,测试用例的设计,测试执行,缺陷等重要的过程。..._测试过程管理中包含哪些过程

政府数字化政务的人工智能与机器学习应用:如何提高政府工作效率-程序员宅基地

文章浏览阅读870次,点赞16次,收藏19次。1.背景介绍政府数字化政务是指政府利用数字技术、互联网、大数据、人工智能等新技术手段,对政府政务进行数字化改革,提高政府工作效率,提升政府服务质量的过程。随着人工智能(AI)和机器学习(ML)技术的快速发展,政府数字化政务中的人工智能与机器学习应用也逐渐成为政府改革的重要内容。政府数字化政务的人工智能与机器学习应用涉及多个领域,包括政策决策、政府服务、公共安全、社会治理等。在这些领域,人工...

ssm+mysql+微信小程序考研刷题平台_mysql刷题软件-程序员宅基地

文章浏览阅读219次,点赞2次,收藏4次。系统主要的用户为用户、管理员,他们的具体权限如下:用户:用户登录后可以对管理员上传的学习视频进行学习。用户可以选择题型进行练习。用户选择小程序提供的考研科目进行相关训练。用户可以进行水平测试,并且查看相关成绩用户可以进行错题集的整理管理员:管理员登录后可管理个人基本信息管理员登录后可管理个人基本信息管理员可以上传、发布考研的相关例题及其分析,并对题型进行管理管理员可以进行查看、搜索考研题目及错题情况。_mysql刷题软件

根据java代码描绘uml类图_Myeclipse8.5下JAVA代码导成UML类图-程序员宅基地

文章浏览阅读1.4k次。myelipse里有UML1和UML2两种方式,UML2功能更强大,但是两者生成过程差别不大1.建立Test工程,如下图,uml包存放uml类图package com.zz.domain;public class User {private int id;private String name;public int getId() {return id;}public void setId(int..._根据以下java代码画出类图

Flume自定义拦截器-程序员宅基地

文章浏览阅读174次。需求:一个topic包含很多个表信息,需要自动根据json字符串中的字段来写入到hive不同的表对应的路径中。发送到Kafka中的数据原本最外层原本没有pkDay和project,只有data和name。因为担心data里面会空值,所以根同事商量,让他们在最外层添加了project和pkDay字段。pkDay字段用于表的自动分区,proejct和name合起来用于自动拼接hive表的名称为 ..._flume拦截器自定义开发 kafka

java同时输入不同类型数据,Java Spring中同时访问多种不同数据库-程序员宅基地

文章浏览阅读380次。原标题:Java Spring中同时访问多种不同数据库 多样的工作要求,可以使用不同的工作方法,只要能获得结果,就不会徒劳。开发企业应用时我们常常遇到要同时访问多种不同数据库的问题,有时是必须把数据归档到某种数据仓库中,有时是要把数据变更推送到第三方数据库中。使用Spring框架时,使用单一数据库是非常容易的,但如果要同时访问多个数据库的话事件就变得复杂多了。本文以在Spring框架下开发一个Sp..._根据输入的不同连接不同的数据库

随便推点

EFT试验复位案例分析_eft电路图-程序员宅基地

文章浏览阅读3.6k次,点赞9次,收藏25次。本案例描述了晶振屏蔽以及开关电源变压器屏蔽对系统稳定工作的影响, 硬件设计时应考虑。_eft电路图

MR21更改价格_mr21 对于物料 zba89121 存在一个当前或未来标准价格-程序员宅基地

文章浏览阅读1.1k次。对于物料价格的更改,可以采取不同的手段:首先,我们来介绍MR21的方式。 需要说明的是,如果要对某一产品进行价格修改,必须满足的前提条件是: ■ 1、必须对价格生效的物料期间与对应会计期间进行开启; ■ 2、该产品在该物料期间未发生物料移动。执行MR21,例如更改物料1180051689的价格为20000元,系统提示“对于物料1180051689 存在一个当前或未来标准价格”,这是因为已经对该..._mr21 对于物料 zba89121 存在一个当前或未来标准价格

联想启天m420刷bios_联想启天M420台式机怎么装win7系统(完美解决usb)-程序员宅基地

文章浏览阅读7.4k次,点赞3次,收藏13次。[文章导读]联想启天M420是一款商用台式电脑,预装的是win10系统,用户还是喜欢win7系统,该台式机采用的intel 8代i5 8500CPU,在安装安装win7时有很多问题,在安装win7时要在BIOS中“关闭安全启动”和“开启兼容模式”,并且安装过程中usb不能使用,要采用联想win7新机型安装,且默认采用的uefi+gpt模式,要改成legacy+mbr引导,那么联想启天M420台式电..._启天m420刷bios

冗余数据一致性,到底如何保证?-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏9次。一,为什么要冗余数据互联网数据量很大的业务场景,往往数据库需要进行水平切分来降低单库数据量。水平切分会有一个patition key,通过patition key的查询能..._保证冗余性

java 打包插件-程序员宅基地

文章浏览阅读88次。是时候闭环Java应用了 原创 2016-08-16 张开涛 你曾经因为部署/上线而痛苦吗?你曾经因为要去运维那改配置而烦恼吗?在我接触过的一些部署/上线方式中,曾碰到过以下一些问题:1、程序代码和依赖都是人工上传到服务器,不是通过工具进行部署和发布;2、目录结构没有规范,jar启动时通过-classpath任意指定;3、fat jar,把程序代码、配置文件和依赖jar都打包到一个jar中,改配置..._那么需要把上面的defaultjavatyperesolver类打包到插件中

VS2015,Microsoft Visual Studio 2005,SourceInsight4.0使用经验,Visual AssistX番茄助手的安装与基本使用9_番茄助手颜色-程序员宅基地

文章浏览阅读909次。1.得下载一个番茄插件,按alt+g才可以有函数跳转功能。2.不安装番茄插件,按F12也可以有跳转功能。3.进公司的VS工程是D:\sync\build\win路径,.sln才是打开工程的方式,一个是VS2005打开的,一个是VS2013打开的。4.公司库里的线程接口,在CmThreadManager.h 里,这个里面是我们的线程库,可以直接拿来用。CreateUserTaskThre..._番茄助手颜色

推荐文章

热门文章

相关标签