C++学习
C++ 条件运算符 ? :
Exp1 ? Exp2 : Exp3;
其中,Exp1、Exp2 和 Exp3 是表达式。请注意冒号的使用和位置。? : 表达式的值取决于 Exp1 的计算结果。如果 Exp1 为真,则Exp1 = Exp2 计算结果。如果 Exp1 为假,则计算 Exp3 的值,且 Exp3 的计算结果则为整个 ? : 表达式的值。
? :也被称为三元运算符
C++类
类的形式,要表明是class 然后是里面的各种东西 但是呢
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。
私有(private)私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。成员和类的默认访问修饰符是 private。
class Box
{
double width;
public:
double length;
void setWidth( double wid );
double getWidth( void );
};
调用class的做法是:
#include <iostream>
using namespace std;
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
int main( )
{
Box Box1; // 声明 Box1,类型为 Box
Box Box2; // 声明 Box2,类型为 Box
double volume = 0.0; // 用于存储体积
// box 1 详述
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 详述
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// box 1 的体积
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Box1 的体积:" << volume <<endl;
// box 2 的体积
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Box2 的体积:" << volume <<endl;
return 0;
}
int main( )
{
Box Box1; // 声明对象 Box1,类型为 Box
Box Box2; // 声明对象 Box2,类型为 Box
对象的时候如此声明。
#include <iostream>
using namespace std;
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
// 成员函数声明
double getVolume(void);
void setLength( double len );
void setBreadth( double bre );
void setHeight( double hei );
}; // 成员函数定义
double Box::getVolume(void)
{
return length * breadth * height;
}
void Box::setLength( double len )
{
length = len;
}
void Box::setBreadth( double bre )
{
breadth = bre;
}
void Box::setHeight( double hei )
{
height = hei;
}
// 程序的主函数
int main( )
{
Box Box1; // 声明 Box1,类型为 Box
Box Box2; // 声明 Box2,类型为 Box
double volume = 0.0; // 用于存储体积
// box 1 详述
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 详述
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// box 1 的体积
volume = Box1.getVolume();
cout << "Box1 的体积:" << volume <<endl;
// box 2 的体积
volume = Box2.getVolume();
cout << "Box2 的体积:" << volume <<endl;
return 0;
}
//这个是类的基本用法,可以看出,如果没有构造函数,那么初始化的时候就非常麻烦。还要不断调用成员函数。但是后面的构造函数就解决了参数初始化的问题,指针就解决了调用成员函数的问题
类成员函数
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。
成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符。所以您可以按照如下方式定义 Volume() 函数:
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
double getVolume(void)
{
return length * breadth * height;
}
};
也可在外面定义
您也可以在类的外部使用**范围解析运算符 :: **定义该函数,如下所示:
double Box::getVolume(void)
{
return length * breadth * height;
}
需要强调一点,在 :: 运算符之前必须使用类名。如果调用成员函数的时候,需要用(.)运算符
Box myBox; // 创建一个对象
myBox.getVolume(); // 调用该对象的成员函数
范围解析运算符 :: 在定义成员函数的时候用
(.)符号在调用成员函数的时候用
构造函数
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
特点:构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于
C++ 指向类的指针
int main(void)
{
Box Box1(3.3, 1.2, 1.5); // Declare box1 Box是一个构造函数
Box Box2(8.5, 6.0, 2.0); // Declare box2
Box *ptrBox; // Declare pointer to a class.
// 保存第一个对象的地址
ptrBox = &Box1;
// 现在尝试使用成员访问运算符来访问成员
cout << "Volume of Box1: " << ptrBox->Volume() << endl;
// 保存第二个对象的地址
ptrBox = &Box2;
// 现在尝试使用成员访问运算符来访问成员
cout << "Volume of Box2: " << ptrBox->Volume() << endl;
return 0;
}
消息订阅器和发布器
下面是一个关于subuscriber和publisher的程序
#include <ros/ros.h>
#include <turtlesim/Velocity.h>
#include <sensor_msgs/Joy.h>
class TeleopTurtle
{
public:
TeleopTurtle(); //一个构造函数
private:
void joyCallback(const sensor_msgs::Joy::ConstPtr& joy); //回调函数
ros::NodeHandle nh_;
int linear_, angular_;
double l_scale_, a_scale_;
ros::Publisher vel_pub_; //在这里定义了publisher 和subscriber
ros::Subscriber joy_sub_; //
};
// %EndTag(CLASSDEF)%
// %Tag(PARAMS)%
TeleopTurtle::TeleopTurtle(): //构造函数的定义
linear_(1),
angular_(2) //这个相当于给linear赋值
{
nh_.param("axis_linear", linear_, linear_);
nh_.param("axis_angular", angular_, angular_);
nh_.param("scale_angular", a_scale_, a_scale_);
nh_.param("scale_linear", l_scale_, l_scale_);
//nh_这个handle相当于c++中的class name,param只是这个类下面的一个对象。
vel_pub_ = nh_.advertise<turtlesim::Velocity>("turtle1/command_velocity", 1);
joy_sub_ = nh_.subscribe<sensor_msgs::Joy>("joy", 10, &TeleopTurtle::joyCallback, this);
}
//定义joyCallback这个回调函数里面采用了vel_pub_这个publisher。使用的流程是这样的,先是joy_sub_订阅了sensor_msgs 的消息,这里面采用了回调函数joyCallback,再回调的时候,又调用了publisher vel_pub_,把速度信息发布到turtle1/command_velocity这个topic
void TeleopTurtle::joyCallback(const sensor_msgs::Joy::ConstPtr& joy)
{
turtlesim::Velocity vel;
vel.angular = a_scale_*joy->axes[angular_];
vel.linear = l_scale_*joy->axes[linear_];
vel_pub_.publish(vel);
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "teleop_turtle");
TeleopTurtle teleop_turtle;
ros::spin();
}
构造函数
构造函数的名字和类完全一样,方便赋值
带参数的构造函数
也是和类的名字一样
折构函数
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
问题总结
- 问:int main(int argc, char* argv[])里的(int argc, char* argv[])是什么意思?为什么要用这个?
我的整理,argc 指的是参数的个数,而argv是运行参数的字符串数组(每个char 表示程序路径名和参数)
答1:很多程序都是带参数运行的,比如WINDOWS命令行下的很多实用程序。参数增加了程序的灵活性。
你可以在“开始”->“运行”中输入cmd进入命令行。
比如一个叫做del的命令,(删除文件),其实就是del.exe,它带参数的,完整的命令格式可以是
del readme.txt
这个命令将删除当前路径下的readme.txt文件(如果有的话);
此时,运行的程序就是del.exe,而readme.txt就是它的参数,
假设del程序的main函数原型为 int main(int argc, char* argv[]),那么
argc = 1,(1个参数)
argv[0] = “readme.txt”(接收的字符串);
假设一个程序的main函数不带任何参数,那么很显然,它仍可以运行,只是,不接收参数罢啦
答2:
void main(int argc, char* argv[ ])
假设程序编译成为 cp.exe
然后在命令行中输入
c:>cp.exe doc1.txt doc2.txt
这行中有三个字符串分别为 cp.exe doc1.txt doc2.txt
则argc为3,即argc是命令行中参数的个数。
char *argv[]为一个指像字符串的数组。
argv[0]="cp.exe"
argv[1]="doc1.txt"
argv[2]="doc2.txt"
即命令行中各各字符串保存在 *argv[]中
- 下面两段程序中,&的位置造成了什么不同?????
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
和
bool add(beginner_tutorials::AddTwoInts::Request &req,
beginner_tutorials::AddTwoInts::Response &res)
{
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.sum);
return true;
}
第一个程序,msg是一个指针,指向std::String的位置,前面的const是定义一个常量指针,也就是说,只能通过指针读取信息,不能写;第二个程序,也是指针,但是不知道区别在哪里。。。。。。
- 类操作里面 (#)和(.)操作分别是什么意思,什么时候用?
范围解析运算符 :: 在定义成员函数的时候用 (.)符号在调用成员函数的时候用
- struct 里面 (.) (->) (&)分别怎么用?
指向结构的指针
您可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似,如下所示:
struct Books *struct_pointer;
现在,您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:
struct_pointer = &Book1;
为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,如下所示:
struct_pointer->title;