Windows编程实验第三课

1通过C++课本复习5.3节(类的静态成员)通过在Qt环境新建non-Qt项目实现这些章节中的代码

#include <iostream>

using namespace std;
class Point
{
public:
    Point(int x=0,int y=0):x(x),y(y) {
        count++;
    }
    Point(Point &p){
        x=p.x;
        y=p.y;
        count++;
    }
    ~Point(){
        count--;
    }
    int getX(){
       return x;
    }
    int getY(){
        return y;
    }
    static void showCount(){
        cout<<"Object count="<<count<<endl;
    }
private:
    int x,y;
    static int count;
};

int Point::count=0;
int main(int argc, char *argv[])
{
    Point a(4,5);
    cout<<"Point A:"<<a.getX()<<","<<a.getY();
    Point::showCount();
    Point b(a);
    cout<<"Point B:"<<b.getX()<<","<<b.getY();
    Point::showCount();
    return 0;

}

2explicit关键字的用法。

1explicit关键字的用法和语法用途。

关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。

C++中, 一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。1 是个构造器2 是个默认且隐含的类型转换操作符。

  所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参数构造器的参数类型, 这时候编译器就自动调用这个构造器, 创建一个AAA的对象。

  这样看起来好象很酷, 很方便。 但在某些情况下(见下面权威的例子), 却违背了我们(程序员)的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用,使用, 不能作为类型转换操作符被隐含的使用。 呵呵, 看来还是光明正大些比较好。

explicit构造函数的作用

  解析:

explicit构造函数是用来防止隐式转换的。请看下面的代码:

class Test1
  {
  public:
  Test1(int n) { num = n; } //普通构造函数
  private:
  int num;
  };
  class Test2
  {
  public:
  explicit Test2(int n) { num = n; } //explicit(显式)构造函数
  private:
  int num;
  };
  int main()
  {
  Test1 t1 = 12; //隐式调用其构造函数, 成功
  Test2 t2 = 12; //编译错误,不能隐式调用其构造函数
  Test2 t3(12); //显示调用成功
  return 0;
  }

Test1的构造函数带一个int型的参数,代码19行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码20行会出现编译错误。

  普通构造函数能够被隐式调用。而explicit构造函数只能被显示调用。

2)为什么C++语言中要有explicit关键字,即它在编程应用中的意义。

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?

如果c++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,如下面所示:

代码如下:

class MyClass
{
public:
 MyClass(int num)
 {
  number=num;
 }

private:
 int number;
};
//.
MyClass obj=10; //ok, convert int to MyClass

在上面的代码中编译器自动将整型转换为MyClass类对象,实际上等同于下面的操作:

代码如下:

MyClass temp(10); 
MyClass obj = temp;

上面的所有的C++ explicit关键字相关的操作即是所谓的"隐式转换"

如果要避免这种自动转换的功能,我们就要使用关键字explicit了,该关键字将类的构造函数声明为"显式",也就是在声明构造函数的时候前面添加上explicit即可,这样就可以防止这种自动的转换操作,

3)为什么java语言可以没有这个关键字。

自动类型转换,也称隐式类型转换,是指不需要书写代码,由系统自动完成的类型转换。由于实际开发中这样的类型转换很多,所以Java语言在设计时,没有为该操作设计语法,而是由JVM自动完成。

转换规则

从存储范围小的类型到存储范围大的类型。

具体规则为:

byteshort(char)intlongfloatdouble

也就是说byte类型的变量可以自动转换为short类型,示例代码:

    byte b = 10;

         short sh = b;

这里在赋值时,JVM首先将b的值转换为short类型,然后再赋值给sh。在类型转换时可以跳跃。示例代码:  

  byte b1 = 100;
         int n = b1;

注意问题在整数之间进行类型转换时,数值不发生改变,而将整数类型,特别是比较大的整数类型转换成小数类型时,由于存储方式不同,有可能存在数据精度的损失。强制类型转换,也称显式类型转换,是指必须书写代码才能完成的类型转换。该类类型转换很可能存在精度的损失,所以必须书写相应的代码,并且能够忍受该种损失时才进行该类型的转换。

3、完成课本3.1节实验,试验5种不同的窗口类型和窗口标志组合。然后:按住Ctrl键,点击“QWidget”,查看Qt源码,注意到枚举的应用,归纳enum关键字的用法,写示例代码运行。

#include "mainwindow.h"
#include<QtWidgets>
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *widget = new QWidget(0,Qt::Dialog);
widget->setWindowTitle(QObject::tr("i am widget"));
QLabel *lable = new QLabel(0,Qt::SplashScreen);
lable->setWindowTitle(QObject::tr("lable:i am window"));
lable->resize(180,20);
QLabel *lable2 = new QLabel(widget);
lable2->setText(QObject::tr("lable2: i am not individual window,only a widget's subcomponent"));
lable2->resize(250,20);
lable->show();
widget->show();
int ret = a.exec();
delete lable;
delete widget;
return ret;

}

QWidget *widget = new QWidget(0,Qt::Dialog);

QLabel *lable = new QLabel(0,Qt::SplashScreen);

将上面两行代码改为下面代码即产生无边框窗口:

QWidget *widget = new QWidget(0,Qt::Dialog|Qt:FramelessWindowHint);

QLabel *lable = new QLabel(0,Qt::SplashScreen|Qt:WindowStayOnTopHint);







猜你喜欢

转载自blog.csdn.net/qq_36946026/article/details/68925132